├── TestWordDocument.docx ├── readme_art └── ReadMeScreenshot.PNG ├── Word-Add-in-JavaScript-MDConversionWeb ├── Images │ ├── Close.png │ ├── AddinIcon.png │ ├── logo-filled.png │ ├── taskpane_16x.png │ ├── taskpane_32x.png │ └── taskpane_80x.png ├── Scripts │ ├── _references.js │ ├── _officeintellisense.js │ └── FabricUI │ │ └── message.banner.js ├── Web.config ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── Home.css ├── Home.html ├── Word-Add-in-JavaScript-MDConversionWeb.csproj ├── Content │ └── message.banner.css ├── SampleContent.js └── Home.js ├── Word-Add-in-MarkdownConversion.yml ├── Word-Add-in-JavaScript-MDConversion ├── Word-Add-in-JavaScript-MDConversionManifest │ ├── SharePointProjectItem.spdata │ └── Word-Add-in-JavaScript-MDConversion.xml └── Word-Add-in-JavaScript-MDConversion.csproj ├── LICENSE ├── Word-Add-in-JavaScript-MDConversion.sln ├── TestMDDocument.md ├── README-Localized ├── README-zh-cn.md ├── README-zh-tw.md ├── README-ja-jp.md ├── README-pt-br.md ├── README-de-de.md ├── README-es-es.md ├── README-ru-ru.md └── README-fr-fr.md ├── README.md ├── Contributing.md └── .gitignore /TestWordDocument.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/Word-Add-in-MarkdownConversion/HEAD/TestWordDocument.docx -------------------------------------------------------------------------------- /readme_art/ReadMeScreenshot.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/Word-Add-in-MarkdownConversion/HEAD/readme_art/ReadMeScreenshot.PNG -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Images/Close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/Word-Add-in-MarkdownConversion/HEAD/Word-Add-in-JavaScript-MDConversionWeb/Images/Close.png -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Images/AddinIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/Word-Add-in-MarkdownConversion/HEAD/Word-Add-in-JavaScript-MDConversionWeb/Images/AddinIcon.png -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Images/logo-filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/Word-Add-in-MarkdownConversion/HEAD/Word-Add-in-JavaScript-MDConversionWeb/Images/logo-filled.png -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Images/taskpane_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/Word-Add-in-MarkdownConversion/HEAD/Word-Add-in-JavaScript-MDConversionWeb/Images/taskpane_16x.png -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Images/taskpane_32x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/Word-Add-in-MarkdownConversion/HEAD/Word-Add-in-JavaScript-MDConversionWeb/Images/taskpane_32x.png -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Images/taskpane_80x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/Word-Add-in-MarkdownConversion/HEAD/Word-Add-in-JavaScript-MDConversionWeb/Images/taskpane_80x.png -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Scripts/_references.js: -------------------------------------------------------------------------------- 1 | /* Required to correctly initalize Office.js for intellisense */ 2 | /// 3 | /* Use offline copy of Office.js for intellisense */ 4 | // /// 5 | // /// 6 | /* Use online copy of Office.js for intellisense */ 7 | /// 8 | /// 9 | -------------------------------------------------------------------------------- /Word-Add-in-MarkdownConversion.yml: -------------------------------------------------------------------------------- 1 | ### YamlMime:Sample 2 | sample: 3 | - name: 'Word add-in: Convert between Word and Markdown formats' 4 | path: '' 5 | description: Use the Word.js APIs to convert a Markdown document to Word for editing and then convert the Word document back to Markdown format, using the Paragraph, Table, List, and Range objects. 6 | readme: '' 7 | generateZip: FALSE 8 | isLive: TRUE 9 | technologies: 10 | - Office Add-ins 11 | azureDeploy: '' 12 | author: rick-kirkham 13 | platforms: [] 14 | languages: 15 | - JavaScript 16 | extensions: 17 | products: 18 | - Word 19 | scenarios: [] 20 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversion/Word-Add-in-JavaScript-MDConversionManifest/SharePointProjectItem.spdata: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Word Add-in Markdown Conversion 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | MIT License 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining 8 | a copy of this software and associated documentation files (the 9 | "Software"), to deal in the Software without restriction, including 10 | without limitation the rights to use, copy, modify, merge, publish, 11 | distribute, sublicense, and/or sell copies of the Software, and to 12 | permit persons to whom the Software is furnished to do so, subject to 13 | the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Word_Add_in_JavaScript_MDConversionWeb")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Word_Add_in_JavaScript_MDConversionWeb")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d046b860-a41d-44b6-9088-d7b356c21450")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversion.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Word-Add-in-JavaScript-MDConversion", "Word-Add-in-JavaScript-MDConversion\Word-Add-in-JavaScript-MDConversion.csproj", "{C45A8254-2B28-4B0B-9710-243614EE79CE}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Word-Add-in-JavaScript-MDConversionWeb", "Word-Add-in-JavaScript-MDConversionWeb\Word-Add-in-JavaScript-MDConversionWeb.csproj", "{D046B860-A41D-44B6-9088-D7B356C21450}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {C45A8254-2B28-4B0B-9710-243614EE79CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {C45A8254-2B28-4B0B-9710-243614EE79CE}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {C45A8254-2B28-4B0B-9710-243614EE79CE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU 19 | {C45A8254-2B28-4B0B-9710-243614EE79CE}.Release|Any CPU.ActiveCfg = Release|Any CPU 20 | {C45A8254-2B28-4B0B-9710-243614EE79CE}.Release|Any CPU.Build.0 = Release|Any CPU 21 | {C45A8254-2B28-4B0B-9710-243614EE79CE}.Release|Any CPU.Deploy.0 = Release|Any CPU 22 | {D046B860-A41D-44B6-9088-D7B356C21450}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {D046B860-A41D-44B6-9088-D7B356C21450}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {D046B860-A41D-44B6-9088-D7B356C21450}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {D046B860-A41D-44B6-9088-D7B356C21450}.Release|Any CPU.Build.0 = Release|Any CPU 26 | EndGlobalSection 27 | GlobalSection(SolutionProperties) = preSolution 28 | HideSolutionNode = FALSE 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Scripts/_officeintellisense.js: -------------------------------------------------------------------------------- 1 | // This file is generated by Visual Studio to enable IntelliSense for the Office JavaScript Object Model. 2 | 3 | var Office = new function() { 4 | this._appContext = 2; 5 | this._showAll = true; 6 | this._setContext = { 7 | 8 | }; 9 | } 10 | 11 | // 1 Excel appContext = 001 12 | // 2 Word appContext = 010 13 | // 3 Word + Excel appContext = 011 14 | // 4 Project appContext = 100 15 | // 5 Project + Excel appContext = 101 16 | // 6 Project + Word appContext = 110 17 | // 7 Project + Word + Excel appContext = 111 18 | // 8 Outlook read-form appContext = 1000 19 | // 16 PowerPoint appContext = 10000 20 | // 17 PowerPoint + Excel appContext = 10001 21 | // 18 PowerPoint + Word appContext = 10010 22 | // 19 PowerPoint + Word + Excel appContext = 10011 23 | // 20 PowerPoint + Project appContext = 10100 24 | // 21 PowerPoint + Project + Excel appContext = 10101 25 | // 22 PowerPoint + Project + Word appContext = 10110 26 | // 23 PowerPoint + Project + Word + Excel appContext = 10111 27 | // 32 Outlook compose-form appContext = 100000 28 | // 40 Outlook read-form + Outlook compose form appContext = 101000 29 | // 64 Access appContext = 1000000 30 | // 65 Access + Excel appContext = 1000001 31 | // 66 Access + Word appContext = 1000010 32 | // 67 Access + Word + Excel appContext = 1000011 33 | // 68 Access + Project appContext = 1000100 34 | // 69 Access + Project + Excel appContext = 1000101 35 | // 70 Access + Project + Word appContext = 1000110 36 | // 71 Access + Project + Word + Excel appContext = 1000111 37 | // 80 Access + PowerPoint appContext = 1010000 38 | // 81 Access + PowerPoint + Excel appContext = 1010001 39 | // 82 Access + PowerPoint + Word appContext = 1010010 40 | // 83 Access + PowerPoint + Word + Excel appContext = 1010011 41 | // 84 Access + PowerPoint + Project appContext = 1010100 42 | // 85 Access + PowerPoint + Project + Excel appContext = 1010101 43 | // 86 Access + PowerPoint + Project + Word appContext = 1010110 44 | // 87 Access + PowerPoint + Project + Word + Excel appContext = 1010111 45 | -------------------------------------------------------------------------------- /TestMDDocument.md: -------------------------------------------------------------------------------- 1 | 2 | # A Sample Document (first level header) 3 | 4 | This document has it all; **bolded** text, *italicized* text, bookmark links, a web link, a table, a code block, and a very complicated list. 5 | 6 | This is another paragraph, because you can't have *too* many. 7 | 8 | ## Table of Contents with Bookmark Links (second level header) 9 | 10 | [Table](#table-second-level-header) 11 | 12 | [Code Block](#code-block-fourth-level-header) 13 | 14 | [Paragraph with Web Link](#paragraph-with-web-link-third-level-header) 15 | 16 | [Complex List](#complex-list-fifth-level-header) 17 | 18 | ## Table (second level header) 19 | 20 | | Name | Mood | Hobby | 21 | |:--|:--|:--| 22 | | Bob | happy | Cooking and baking | 23 | | Sally | wistful | Running marathons **barefoot** | 24 | | Mary | energetic | Playing multiple games of chess simultaneously | 25 | 26 | #### Code Block (fourth level header) 27 | 28 | ``` 29 | // This code is only here to illustrate a code block. 30 | Word.run(function (context) { 31 | var body = context.document.body; 32 | body.clear(); 33 | return context.sync().then(function () { 34 | console.log('Cleared the body contents.'); 35 | }); 36 | }) 37 | ``` 38 | 39 | ### Paragraph with Web Link (third level header) 40 | 41 | For more information about Office host application and server requirements, see [Requirements for running Office Add-ins](https://msdn.microsoft.com/EN-US/library/office/dn833104.aspx). 42 | 43 | ##### Complex List (fifth level header) 44 | 45 | There can be up to nine levels in a list. 46 | 47 | * Top level is bullet 48 | * Second level is bullet 49 | * Another second level item 50 | 1. Third level is numeric 51 | 1. Fourth level is numeric 52 | 1. Another fourth level item. 53 | * Fifth level is bullet 54 | 1. Sixth level is numeric 55 | 1. Another sixth level item 56 | * Back to the fifth level 57 | * Back to the sixth level 58 | * Seventh is bullet 59 | 1. Eighth is numeric 60 | * Ninth is bullet 61 | * Another ninth level item 62 | 1. Another eighth level item 63 | * Another seventh level 64 | * Another sixth level item 65 | 1. Another fourth level item 66 | 1. Another third level item 67 | * Another second level item 68 | * Another top level item 69 | -------------------------------------------------------------------------------- /README-Localized/README-zh-cn.md: -------------------------------------------------------------------------------- 1 | # 直接转换 Word 和 Markdown 格式的 Office 外接程序 2 | 3 | 使用 Word.js API 将 Markdown 文档转换成 Word 格式以供编辑,然后使用 Paragraph、Table、List 和 Range 对象将 Word 文档转换回 Markdown 格式。 4 | 5 | ![转换 Word 和 Markdown 格式](../readme_art/ReadMeScreenshot.PNG) 6 | 7 | ## 目录 8 | * [修订记录](#change-history) 9 | * [先决条件](#prerequisites) 10 | * [测试外接程序](#test-the-add-in) 11 | * [已知问题](#known-issues) 12 | * [问题和意见](#questions-and-comments) 13 | * [其他资源](#additional-resources) 14 | 15 | ## 修订记录 16 | 17 | 2016 年 12 月 16 日: 18 | 19 | * 首版。 20 | 21 | ## 先决条件 22 | 23 | * Visual Studio 2015 或更高版本。 24 | * Word 2016 for Windows(内部版本 16.0.6727.1000 或更高版本)。 25 | 26 | ## 测试外接程序 27 | 28 | 1. 将项目克隆或下载到桌面。 29 | 2. 在 Visual Studio 中,打开 Word-Add-in-JavaScript-MDConversion.sln 文件。 30 | 2. 按 F5。 31 | 3. 在 Word 启动后,按“**主页**”功能区上的“**打开转换器**”按钮。 32 | 4. 在应用程序已加载后,按“**插入测试 Markdown 文档**”按钮。 33 | 5. 在示例 Markdown 文本已加载后,按“**将 MD 文本转换成 Word**”按钮。 34 | 6. 在将文档转换成 Word 格式后,编辑文档。 35 | 7. 按“**将文档转换成 Markdown 格式**”按钮。 36 | 8. 转换文档后,将文档内容复制并粘贴到 Markdown 预览器(如 Visual Studio Code)中。 37 | 9. 也可以先按“**插入测试 Word 文档**”按钮,然后将创建的示例 Word 文档转换成 Markdown 格式。 38 | 10. (可选)从你自己的 Markdown 文本或 Word 内容入手,测试外接程序。 39 | 40 | ## 已知问题 41 | 42 | - 由于以编程方式创建的 Word 列表的创建方式有 bug,因此在转换 Markdown 和 Word 格式时,只能正确转换文档中的第一个列表(或有时为前两个列表)。(所有 Markdown 列表都会正确转换成 Word 格式。) 43 | - 如果对同一文档重复来回转换 Word 和 Markdown 格式,表中的所有行都会采用标题行格式,这通常包括粗体文本。 44 | - 外接程序会使用 Word Online 尚不支持的部分 Office API(截至 2017 年 2 月 15 日)。应在桌面 Word 中对其进行测试(在按 F5 时它将自动打开。 45 | 46 | ## 问题和意见 47 | 48 | 我们乐意倾听你对此示例的反馈。你可以在此存储库中的“*问题*”部分向我们发送反馈。 49 | 50 | 与 Microsoft Office 365 开发相关的一般问题应发布到 [Stack Overflow](http://stackoverflow.com/questions/tagged/office-js+API)。如果你的问题是关于 Office JavaScript API,请务必为问题添加 [office-js] 和 [API].标记。 51 | 52 | ## 其他资源 53 | 54 | * 55 | [Office 外接程序文档](https://msdn.microsoft.com/en-us/library/office/jj220060.aspx) 56 | * [Office 开发人员中心](http://dev.office.com/) 57 | * 有关更多 Office 外接程序示例,请访问 [Github 上的 OfficeDev](https://github.com/officedev)。 58 | 59 | ## 版权 60 | 版权所有 (c) 2016 Microsoft Corporation。保留所有权利。 61 | 62 | 63 | 64 | 此项目已采用 [Microsoft 开放源代码行为准则](https://opensource.microsoft.com/codeofconduct/)。有关详细信息,请参阅[行为准则 FAQ](https://opensource.microsoft.com/codeofconduct/faq/)。如有其他任何问题或意见,也可联系 [opencode@microsoft.com](mailto:opencode@microsoft.com)。 65 | -------------------------------------------------------------------------------- /README-Localized/README-zh-tw.md: -------------------------------------------------------------------------------- 1 | # 在 Word 與 Markdown 格式間直接轉換的 Office 增益集 2 | 3 | 使用 Word.js Api 將 Markdown 文件轉換成 Word 來進行編輯,然後再使用 Paragraph、Table、List 和 Range 物件,將 Word 文件轉換回 Markdown 格式。 4 | 5 | ![在 Word 和 Markdown 間轉換](../readme_art/ReadMeScreenshot.PNG) 6 | 7 | ## 目錄 8 | * [變更歷程記錄](#change-history) 9 | * [先決條件](#prerequisites) 10 | * [測試增益集](#test-the-add-in) 11 | * [已知問題](#known-issues) 12 | * [問題和建議](#questions-and-comments) 13 | * [其他資源](#additional-resources) 14 | 15 | ## 變更歷程記錄 16 | 17 | 2016 年 12 月 16 日: 18 | 19 | * 初始版本。 20 | 21 | ## 先決條件 22 | 23 | * Visual Studio 2015 或更新版本。 24 | * Word 2016 for Windows,組建 16.0.6727.1000 或更新版本。 25 | 26 | ## 測試增益集 27 | 28 | 1. 將專案複製或下載到您的桌面。 29 | 2. 在 Visual Studio 中開啟 Word-Add-in-JavaScript-MDConversion.sln 檔案。 30 | 2. 按下 F5。 31 | 3. 在 Word 啟動後,按下 [常用]**** 功能區上的 [開啟轉換器]**** 按鈕。 32 | 4. 當應用程式載入時,按下按鈕 [插入測試 Markdown 文件]****。 33 | 5. 在範例 Markdown 文字載入之後,按下按鈕 [將 MD 文字轉換成 Word]****。 34 | 6. 在文件轉換成 Word 後,編輯該文件。 35 | 7. 按下按鈕 [將文件轉換為 Markdown]****。 36 | 8. 在文件轉換後,請將其內容複製並貼入 Markdown 預覽程式 (例如 Visual Studio Code)。 37 | 9. 或者,您可以開始使用按鈕 [插入測試 Word 文件]****,並將建立的範例 Word 文件轉換成 Markdown。 38 | 10. 或者,開始使用您自己的 Markdown 文字或 Word 內容,並測試增益集。 39 | 40 | ## 已知問題 41 | 42 | - 因為 programmatically-created Word 清單建立方式的問題,Markdown-to-Word 只會順利轉換文件中的第一個清單 (有時候為前兩個清單)。(所有 Markdown 清單將會順利轉換為 Word。) 43 | - 如果您在 Word 和 Markdown 之間來回重複轉換相同文件時,資料表中所有資料列將會採用標題列的格式 (通常包含粗體文字)。 44 | - 增益集會使用 Word Online 中尚未支援的某些 Office API (至 2017 年 2 月 15 日為止)。您應該在桌面的 Word 進行測試 (當您按下 F5 時會自動開啟)。 45 | 46 | ## 問題和建議 47 | 48 | 我們很樂於收到您對於此範例的意見反應。您可以在此存放庫的 [問題]** 區段中,將您的意見反應傳送給我們。 49 | 50 | 請在 [Stack Overflow](http://stackoverflow.com/questions/tagged/office-js+API) 提出有關 Microsoft Office 365 開發的一般問題。如果您的問題是關於 Office JavaScript API,請確定您的問題標記有 [office js] 與 [API]。 51 | 52 | ## 其他資源 53 | 54 | * 55 | [Office 增益集文件](https://msdn.microsoft.com/en-us/library/office/jj220060.aspx) 56 | * [Office 開發人員中心](http://dev.office.com/) 57 | * 在 [Github 上的 OfficeDev](https://github.com/officedev) 中有更多 Office 增益集範例 58 | 59 | ## 著作權 60 | Copyright (c) 2016 Microsoft Corporation.著作權所有,並保留一切權利。 61 | 62 | 63 | 64 | 此專案已採用 [Microsoft 開放原始碼管理辦法](https://opensource.microsoft.com/codeofconduct/)。如需詳細資訊,請參閱[管理辦法常見問題集](https://opensource.microsoft.com/codeofconduct/faq/),如果有其他問題或意見,請連絡 [opencode@microsoft.com](mailto:opencode@microsoft.com)。 65 | -------------------------------------------------------------------------------- /README-Localized/README-ja-jp.md: -------------------------------------------------------------------------------- 1 | # Word 形式と Markdown 形式間の変換を直接行う Office アドイン 2 | 3 | Markdown ドキュメントを編集用に Word に変換した後、Paragraph、Table、List、および Range の各オブジェクトを使用して再び Markdown 形式に変換するには、Word.js API を使用します。 4 | 5 | ![Word と Markdown 間の変換](../readme_art/ReadMeScreenshot.PNG) 6 | 7 | ## 目次 8 | * [変更履歴](#change-history) 9 | * [前提条件](#prerequisites) 10 | * [アドインをテストする](#test-the-add-in) 11 | * [既知の問題](#known-issues) 12 | * [質問とコメント](#questions-and-comments) 13 | * [その他のリソース](#additional-resources) 14 | 15 | ## 変更履歴 16 | 17 | 2016 年 12 月 16 日 18 | 19 | * 初期バージョン。 20 | 21 | ## 前提条件 22 | 23 | * Visual Studio 2015 以降。 24 | * Word 2016 for Windows (16.0.6727.1000 以降のビルド)。 25 | 26 | ## アドインをテストする 27 | 28 | 1. プロジェクトをデスクトップに複製またはダウンロードします。 29 | 2. Visual Studio で Word-Add-in-JavaScript-MDConversion.sln ファイルを開きます。 30 | 2. F5 キーを押します。 31 | 3. Word が起動したら、**[ホーム]** リボンの **[コンバーターを開く]** ボタンを押します。 32 | 4. アプリケーションが読み込まれたら、**[テスト用 Markdown 文書を挿入する]** ボタンを押します。 33 | 5. サンプルの Markdown テキストが読み込まれたら、**[MD テキストを Word に変換する]** ボタンを押します。 34 | 6. 文書が Word に変換されたら編集します。 35 | 7. **[文書を Markdown に変換する]** ボタンを押します。 36 | 8. 文書が変換されたら、内容をコピーして、Markdown プレビューアー (Visual Studio Code など) に貼り付けます。 37 | 9. あるいは、**[テスト用 Word 文書を挿入する]** ボタンから始めて、作成されたサンプルの Word 文書を Markdown に変換します。 38 | 10. 必要に応じて、Markdown テキストまたは Word コンテンツから始めて、アドインをテストします。 39 | 40 | ## 既知の問題 41 | 42 | - プログラムによって作成される Word のリストの作成方法にバグがあるため、Markdown から Word への変換は、文書内の最初のリスト (または最初の 2 つのリストの場合もあります) のみが正しく行われます。(任意の数の Markdown リストは正しく Word に変換されます。) 43 | - Word と Markdown 間で繰り返し同じ文書を変換したり、元に戻したりする場合、表内のすべての行はヘッダー行の形式に従います。通常は太字も含まれます。 44 | - アドインは、2017 年 2 月 15 日現在、Word Online でサポートされていないいくつかの Office API を使用します。デスクトップ用の Word (F5 キーを押すと自動的に開きます) でテストすることをお勧めします。 45 | 46 | ## 質問とコメント 47 | 48 | このサンプルに関するフィードバックをお寄せください。このリポジトリの「*問題*」セクションでフィードバックを送信できます。 49 | 50 | Microsoft Office 365 開発全般の質問につきましては、「[スタック オーバーフロー](http://stackoverflow.com/questions/tagged/office-js+API)」に投稿してください。Office JavaScript API に関する質問の場合は、必ず質問に [office-js] と [API] のタグを付けてください。 51 | 52 | ## 追加リソース 53 | 54 | * 55 | [Office アドインのドキュメント](https://msdn.microsoft.com/en-us/library/office/jj220060.aspx) 56 | * [Office デベロッパー センター](http://dev.office.com/) 57 | * [Github の OfficeDev](https://github.com/officedev) にあるその他の Office アドイン サンプル 58 | 59 | ## 著作権 60 | Copyright (c) 2016 Microsoft Corporation.All rights reserved. 61 | 62 | 63 | 64 | このプロジェクトでは、[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) が採用されています。詳細については、「[Code of Conduct の FAQ](https://opensource.microsoft.com/codeofconduct/faq/)」を参照してください。また、その他の質問やコメントがあれば、[opencode@microsoft.com](mailto:opencode@microsoft.com) までお問い合わせください。 65 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Home.css: -------------------------------------------------------------------------------- 1 | /* Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See full license in root of repo. */ 2 | 3 | /* 4 | This file provides the styles for the add-in pages. 5 | */ 6 | 7 | html, body { 8 | width: 100%; 9 | height: 100%; 10 | margin: 0; 11 | padding: 0; 12 | overflow: auto; } 13 | 14 | body { 15 | position: relative; 16 | font-size: 16px; } 17 | 18 | main { 19 | height: 100%; 20 | overflow-y: auto; } 21 | 22 | footer { 23 | width: 100%; 24 | position: relative; 25 | bottom: 0; } 26 | 27 | p, h1, h2, h3, h4, h5, h6 { 28 | margin: 0; 29 | padding: 0; } 30 | 31 | ul { 32 | padding: 0; } 33 | 34 | 35 | .padding { 36 | padding-bottom: 15px; 37 | } 38 | 39 | .ms-navigation { 40 | display: -webkit-flex; 41 | display: flex; 42 | -webkit-flex-direction: column; 43 | flex-direction: column; 44 | -webkit-flex-wrap: nowrap; 45 | flex-wrap: nowrap; 46 | height: 100%; } 47 | 48 | .ms-navigation__content { 49 | -webkit-flex: 1 0 0px; 50 | flex: 1 0 0px; 51 | padding-top: 15px; 52 | padding-left: 20px; 53 | padding-right: 20px; 54 | margin-top: 0px; } 55 | 56 | .ms-navigation__content p { 57 | padding-top: 10px; } 58 | 59 | .ms-navigation__content ul { 60 | list-style: none; } 61 | 62 | .ms-navigation__content__title, .ms-navigation__content__subtitle, .ms-navigation__content__text { 63 | margin-bottom: 20px; 64 | margin-top: 20px; 65 | } 66 | 67 | .ms-navigation__header { 68 | overflow: hidden; 69 | padding-left: 0px; 70 | padding-right: 0px; 71 | background-color: #DEECF9; 72 | height: 40px; } 73 | 74 | .ms-landing-page__footer { 75 | display: -webkit-inline-flex; 76 | display: inline-flex; 77 | -webkit-justify-content: center; 78 | justify-content: center; 79 | -webkit-align-items: center; 80 | align-items: center; 81 | position: absolute; 82 | bottom: 0;} 83 | 84 | .ms-landing-page__footer--left { 85 | transition: background ease 0.1s, color ease 0.1s; 86 | display: -webkit-inline-flex; 87 | display: inline-flex; 88 | -webkit-justify-content: flex-start; 89 | justify-content: flex-start; 90 | -webkit-align-items: center; 91 | align-items: center; 92 | -webkit-flex: 1 0 0px; 93 | flex: 1 0 0px; 94 | padding: 20px; } 95 | 96 | .ms-landing-page__footer--left:active, .ms-landing-page__footer--left:hover { 97 | background: #005ca4; 98 | cursor: pointer; } 99 | 100 | .ms-landing-page__footer--left:active { 101 | background: #005ca4; } 102 | 103 | .ms-landing-page__footer--left--disabled { 104 | opacity: 0.6; 105 | pointer-events: none; 106 | cursor: not-allowed; } 107 | 108 | .ms-landing-page__footer--left--disabled:active, .ms-landing-page__footer--left--disabled:hover { 109 | background: transparent; } 110 | 111 | .ms-landing-page__footer--left img { 112 | width: 40px; 113 | height: 40px; } 114 | 115 | .ms-landing-page__footer--left h1 { 116 | -webkit-flex: 1 0 0px; 117 | flex: 1 0 0px; 118 | margin-left: 15px; 119 | text-align: left; 120 | width: auto; 121 | max-width: auto; 122 | overflow: hidden; 123 | white-space: nowrap; 124 | text-overflow: ellipsis; } 125 | 126 | .ms-landing-page__footer--right { 127 | transition: background ease 0.1s, color ease 0.1s; 128 | padding: 29px 20px; } 129 | 130 | .ms-landing-page__footer--right:active, .ms-landing-page__footer--right:hover { 131 | background: #005ca4; 132 | cursor: pointer; } 133 | 134 | .ms-landing-page__footer--right:active { 135 | background: #005ca4; } 136 | 137 | .ms-landing-page__footer--right--disabled { 138 | opacity: 0.6; 139 | pointer-events: none; 140 | cursor: not-allowed; } 141 | 142 | .ms-landing-page__footer--right--disabled:active, .ms-landing-page__footer--right--disabled:hover { 143 | background: transparent; } 144 | 145 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Home.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Word Add-In Markdown Conversion 10 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 |
33 |
34 |
35 |
36 | 37 |
38 |
39 | 40 |
41 | 42 |
43 |
44 |
45 | Convert from Word to Markdown 46 |
47 |
48 | 51 |
52 | 55 |
Convert from Markdown to Word
56 |
57 | 60 |
61 | 64 |
65 |
66 | 70 |
71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversion/Word-Add-in-JavaScript-MDConversion.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C45A8254-2B28-4B0B-9710-243614EE79CE} 8 | Library 9 | Properties 10 | Word_Add_in_JavaScript_MDConversion 11 | Word-Add-in-JavaScript-MDConversion 12 | v4.5 13 | 15.0 14 | 512 15 | {C1CDDADD-2546-481F-9697-4EA41081F2FC};{14822709-B5A1-4724-98CA-57A101D1B079};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 16 | False 17 | {98154bdd-2f56-45bd-8e77-718f466df89d} 18 | {3c520555-1460-4659-ba0d-b282618f89d5} 19 | {9a0e8e96-2a51-4298-86a6-136a30a4d667} 20 | {621111df-f93b-466f-b9d8-e927b95ccda4} 21 | {75c167cd-67b7-4bfc-8c62-247da1fdc5e6} 22 | OfficeApp 23 | 14.0 24 | 14.0 25 | 26 | 27 | true 28 | full 29 | false 30 | bin\Debug\ 31 | DEBUG;TRACE 32 | prompt 33 | 4 34 | false 35 | 36 | 37 | pdbonly 38 | true 39 | bin\Release\ 40 | TRACE 41 | prompt 42 | 4 43 | false 44 | 45 | 46 | 47 | {33b7a7f9-4c2b-4a9b-89fa-a5dd0bd99619} 48 | 49 | 50 | manifest-oemanifest 51 | 52 | 53 | 54 | 55 | {D046B860-A41D-44B6-9088-D7B356C21450} 56 | Word-Add-in-JavaScript-MDConversionWeb 57 | True 58 | Web 59 | SharePointWebProjectOutput 60 | Word-Add-in-JavaScript-MDConversionWeb 61 | False 62 | 63 | 64 | 65 | 10.0 66 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 67 | 68 | 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [ARCHIVED] Office Add-in that converts directly between Word and Markdown formats 2 | 3 | **Note:** This repo is archived and no longer actively maintained. Security vulnerabilities may exist in the project, or its dependencies. If you plan to reuse or run any code from this repo, be sure to perform appropriate security checks on the code or dependencies first. Do not use this project as the starting point of a production Office Add-in. Always start your production code by using the Office/SharePoint development workload in Visual Studio, or the [Yeoman generator for Office Add-ins](https://github.com/OfficeDev/generator-office), and follow security best practices as you develop the add-in. 4 | Use the Word.js APIs to convert a Markdown document to Word for editing and then convert the Word document back to Markdown format, using the Paragraph, Table, List, and Range objects. 5 | 6 | ![Convert between Word and Markdown](readme_art/ReadMeScreenshot.PNG) 7 | 8 | ## Table of Contents 9 | * [Change history](#change-history) 10 | * [Prerequisites](#prerequisites) 11 | * [Test the add-in](#test-the-add-in) 12 | * [Known issues](#known-issues) 13 | * [Questions and comments](#questions-and-comments) 14 | * [Additional resources](#additional-resources) 15 | 16 | ## Change history 17 | 18 | December 16, 2016: 19 | 20 | * Initial version. 21 | 22 | ## Prerequisites 23 | 24 | * Visual Studio 2015 or later. 25 | * Word 2016 for Windows, build 16.0.6727.1000 or later. 26 | 27 | ## Test the add-in 28 | 29 | 1. Clone or download the project to your desktop. 30 | 2. Open the Word-Add-in-JavaScript-MDConversion.sln file in Visual Studio. 31 | 2. Press F5. 32 | 3. After Word launches, press the **Open Converter** button on the **Home** ribbon. 33 | 4. When the application has loaded, press the button **Insert test Markdown document**. 34 | 5. After the sample Markdown text has loaded, press the button **Convert MD text to Word**. 35 | 6. After the document has been converted to Word, edit it. 36 | 7. Press the button **Convert document to Markdown**. 37 | 8. After the document has converted, copy and paste its contents into a Markdown previewer, such as Visual Studio Code. 38 | 9. Alternatively, you can start with the button **Insert test Word document** and convert the sample Word document that is created to Markdown. 39 | 10. Optionally, start with your own Markdown text or Word content and test the add-in. 40 | 41 | ## Known issues 42 | 43 | - Due to a bug in the way that programmatically-created Word lists are created, the Markdown-to-Word will only correctly convert the first list (or sometimes the first two lists) in a document. (Any number of Markdown lists will convert correctly to Word.) 44 | - If you convert the same document repeatedly between Word and Markdown back and forth, all of the rows in tables will take on the formatting of the header row, which usually includes bold text. 45 | - The add-in uses some Office APIs that are not yet supported in Word Online (as of 2017/2/15). You should test it in desktop Word (which opens automatically when you press F5. 46 | 47 | ## Questions and comments 48 | 49 | We'd love to get your feedback about this sample. You can send your feedback to us in the *Issues* section of this repository. 50 | 51 | Questions about Microsoft Office 365 development in general should be posted to [Stack Overflow](http://stackoverflow.com/questions/tagged/office-js+API). If your question is about the Office JavaScript APIs, make sure that your questions are tagged with [office-js] and [API]. 52 | 53 | ## Additional resources 54 | 55 | * [Office add-in documentation](https://msdn.microsoft.com/en-us/library/office/jj220060.aspx) 56 | * [Office Dev Center](http://dev.office.com/) 57 | * More Office Add-in samples at [OfficeDev on Github](https://github.com/officedev) 58 | 59 | ## Copyright 60 | Copyright (c) 2016 Microsoft Corporation. All rights reserved. 61 | 62 | 63 | 64 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 65 | -------------------------------------------------------------------------------- /README-Localized/README-pt-br.md: -------------------------------------------------------------------------------- 1 | # Suplemento do Office que converte diretamente entre os formatos Word e Markdown 2 | 3 | Use as APIs do Word.js para converter um documento Markdown para o Word para edição e converta o documento do Word para o formato Markdown usando os objetos Paragraph, Table, List e Range. 4 | 5 | ![Converter entre Word e Markdown](../readme_art/ReadMeScreenshot.PNG) 6 | 7 | ## Sumário 8 | * [Histórico de alterações](#change-history) 9 | * [Pré-requisitos](#prerequisites) 10 | * [Testar o suplemento](#test-the-add-in) 11 | * [Problemas conhecidos](#known-issues) 12 | * [Perguntas e comentários](#questions-and-comments) 13 | * [Recursos adicionais](#additional-resources) 14 | 15 | ## Histórico de alterações 16 | 17 | 16 de dezembro de 2016: 18 | 19 | * Versão inicial. 20 | 21 | ## Pré-requisitos 22 | 23 | * Visual Studio 2015 ou posterior. 24 | * Word 2016 para Windows, build 16.0.6727.1000 ou superior. 25 | 26 | ## Testar o suplemento 27 | 28 | 1. Clone ou baixe o projeto para sua área de trabalho. 29 | 2. Abra o arquivo Word-Add-in-JavaScript-MDConversion.sln no Visual Studio. 30 | 2. Pressione F5. 31 | 3. Depois que o Word for iniciado, pressione o botão **Abrir Conversor** na faixa de opções **Página Inicial**. 32 | 4. Quando o aplicativo for carregado, pressione o botão **Inserir documento Markdown de teste**. 33 | 5. Depois que o texto Markdown de exemplo for carregado, pressione o botão **Converter texto MD para o Word**. 34 | 6. Depois que o documento tiver sido convertido para o Word, edite-o. 35 | 7. Pressione o botão **Converter documento para Markdown**. 36 | 8. Depois que o documento for convertido, copie e cole seu conteúdo em um visualizador para Markdown, como o Visual Studio Code. 37 | 9. Como alternativa, você pode começar com o botão **Inserir documento Word de teste** e converter o documento Word de exemplo criado para Markdown. 38 | 10. Opcionalmente, comece com seu próprio texto Markdown ou conteúdo do Word e teste o suplemento. 39 | 40 | ## Problemas conhecidos 41 | 42 | - Devido a um bug na maneira que as listas do Word criadas por programação são criadas, o Markdown para Word só converterá corretamente a primeira lista (ou às vezes as duas primeiras listas) em um documento. (Qualquer número de listas do Markdown será convertido corretamente para o Word.) 43 | - Quando você converte o mesmo documento repetidamente entre o Word e o Markdown, todas as linhas das tabelas assumem a formatação da linha de cabeçalho, que geralmente inclui texto em negrito. 44 | - O suplemento usa algumas APIs do Office que ainda não têm suporte no Word Online (desde 15/02/2017). Você deve testá-lo no Word para área de trabalho (pressione F5 para abri-lo automaticamente). 45 | 46 | ## Perguntas e comentários 47 | 48 | Gostaríamos de saber sua opinião sobre este exemplo. Você pode nos enviar comentários na seção *Issues* deste repositório. 49 | 50 | As perguntas sobre o desenvolvimento do Microsoft Office 365 em geral devem ser postadas no [Stack Overflow](http://stackoverflow.com/questions/tagged/office-js+API). Se sua pergunta estiver relacionada às APIs JavaScript para Office, não deixe de marcá-la com as tags [office-js] e [API]. 51 | 52 | ## Recursos adicionais 53 | 54 | * 55 | [Documentação dos suplementos do Office](https://msdn.microsoft.com/en-us/library/office/jj220060.aspx) 56 | * [Centro de Desenvolvimento do Office](http://dev.office.com/) 57 | * Confira outros exemplos de Suplemento do Office em [OfficeDev no Github](https://github.com/officedev) 58 | 59 | ## Copyright 60 | Copyright (c) 2016 Microsoft Corporation. Todos os direitos reservados. 61 | 62 | 63 | 64 | Este projeto adotou o [Código de Conduta de Software Livre da Microsoft](https://opensource.microsoft.com/codeofconduct/). Para saber mais, confira as [Perguntas frequentes sobre o Código de Conduta](https://opensource.microsoft.com/codeofconduct/faq/) ou contate [opencode@microsoft.com](mailto:opencode@microsoft.com) se tiver outras dúvidas ou comentários. 65 | -------------------------------------------------------------------------------- /README-Localized/README-de-de.md: -------------------------------------------------------------------------------- 1 | # Office-Add-in, das eine direkt Konvertierung zwischen Word- und Markdown-Formaten durchführt 2 | 3 | Verwenden Sie die Word.js-APIs, um ein Markdown-Dokument in Word zu konvertieren, und konvertieren Sie dann das Word-Dokument mithilfe der Paragraph-, Table, List- und Range-Objekte zurück in das Markdown-Format. 4 | 5 | ![Konvertierung zwischen Word und Markdown](../readme_art/ReadMeScreenshot.PNG) 6 | 7 | ## Inhalt 8 | * [Änderungsverlauf](#change-history) 9 | * [Voraussetzungen](#prerequisites) 10 | * [Testen des Add-Ins](#test-the-add-in) 11 | * [Bekannte Probleme](#known-issues) 12 | * [Fragen und Kommentare](#questions-and-comments) 13 | * [Zusätzliche Ressourcen](#additional-resources) 14 | 15 | ## Änderungsverlauf 16 | 17 | 16. Dezember 2016 18 | 19 | * Ursprüngliche Version 20 | 21 | ## Voraussetzungen 22 | 23 | * Visual Studio 2015 oder höher. 24 | * Word 2016 für Windows, Build 16.0.6727.1000 oder höher 25 | 26 | ## Testen des Add-Ins 27 | 28 | 1. Klonen Sie das Projekt auf Ihrem Desktop, oder laden Sie es herunter. 29 | 2. Öffnen Sie die Datei „Word-Add-in-JavaScript-MDConversion.sln“ in Visual Studio. 30 | 2. Drücken Sie F5. 31 | 3. Nachdem Word gestartet wurde, drücken Sie die Schaltfläche **Konverter öffnen** Schaltfläche auf dem Menüband **Start**. 32 | 4. Wenn die Anwendung geladen wurde, drücken Sie die Schaltfläche **Markdown-Testdokument einfügen**. 33 | 5. Nachdem der Beispiel-Markdowntext geladen wurde, drücken Sie die Schaltfläche **MD-Text in Word konvertieren**. 34 | 6. Bearbeiten Sie das Dokument, nachdem es in Word konvertiert wurde. 35 | 7. Drücken Sie die Schaltfläche **Dokument in Markdown konvertieren**. 36 | 8. Nachdem das Dokument konvertiert wurde, kopieren Sie seinen Inhalt in eine Markdown-Vorschau, z. B. Visual Studio Code. 37 | 9. Alternativ können Sie mit der Schaltfläche **Word-Testdokument einfügen** beginnen und das erstellte Word-Beispieldokument in Markdown konvertieren. 38 | 10. Beginnen Sie optional mit Ihrem eigenen Markdown-Text oder Word-Inhalt, und testen Sie das Add-In. 39 | 40 | ## Bekannte Probleme 41 | 42 | - Aufgrund eines Fehlers in der Art und Weise, wie programmgesteuert erstellte Word-Listen erstellt werden, wird mit Markdown-to-Word nur die erste Liste (oder manchmal die beiden ersten Listen) in einem Dokument korrekt konvertiert. (Eine beliebige Anzahl von Markdown-Listen wird korrekt in Word konvertiert.) 43 | - Wenn Sie dasselbe Dokument wiederholt zwischen Word und Markdown hin und her konvertieren, verwenden alle Zeilen in der Tabelle die Formatierung der Kopfzeile, die in der Regel fett formatierten Text enthält. 44 | - Das Add-In verwendet einige Office-APIs, die in Word Online noch nicht unterstützt werden (Stand 15.02.2017). Sie sollten es in der Word-Desktopanwendung testen (die automatisch geöffnet wird, wenn Sie F5 drücken). 45 | 46 | ## Fragen und Kommentare 47 | 48 | Wir schätzen Ihr Feedback hinsichtlich dieses Beispiels. Sie können uns Ihr Feedback über den Abschnitt *Probleme* dieses Repositorys senden. 49 | 50 | Fragen zur Microsoft Office 365-Entwicklung sollten in [Stack Overflow](http://stackoverflow.com/questions/tagged/office-js+API) gestellt werden. Wenn Ihre Frage die Office JavaScript-APIs betrifft, sollte die Frage mit [office-js] und [API] kategorisiert sein. 51 | 52 | ## Zusätzliche Ressourcen 53 | 54 | * 55 | [Dokumentation zu Office-Add-Ins](https://msdn.microsoft.com/en-us/library/office/jj220060.aspx) 56 | * [Office Dev Center](http://dev.office.com/) 57 | * Weitere Office-Add-In-Beispiele unter [OfficeDev auf Github](https://github.com/officedev) 58 | 59 | ## Copyright 60 | Copyright (c) 2016 Microsoft Corporation. Alle Rechte vorbehalten. 61 | 62 | 63 | 64 | In diesem Projekt wurden die [Microsoft Open Source-Verhaltensregeln](https://opensource.microsoft.com/codeofconduct/) übernommen. Weitere Informationen finden Sie unter [Häufig gestellte Fragen zu Verhaltensregeln](https://opensource.microsoft.com/codeofconduct/faq/), oder richten Sie Ihre Fragen oder Kommentare an [opencode@microsoft.com](mailto:opencode@microsoft.com). 65 | -------------------------------------------------------------------------------- /README-Localized/README-es-es.md: -------------------------------------------------------------------------------- 1 | # Complemento de Office que convierte directamente del formato de Word a Markdown y viceversa 2 | 3 | Use las API Word.js para convertir un documento Markdown a Word para la edición y, a continuación, convertir el documento de Word de nuevo al formato Markdown mediante los objetos Párrafo, Tabla, Lista e Intervalo. 4 | 5 | ![Convertir de Word a Markdown y viceversa](../readme_art/ReadMeScreenshot.PNG) 6 | 7 | ## Tabla de contenido 8 | * [Historial de cambios](#change-history) 9 | * [Requisitos previos](#prerequisites) 10 | * [Probar el complemento](#test-the-add-in) 11 | * [Problemas conocidos](#known-issues) 12 | * [Preguntas y comentarios](#questions-and-comments) 13 | * [Recursos adicionales](#additional-resources) 14 | 15 | ## Historial de cambios 16 | 17 | 16 de diciembre de 2016: 18 | 19 | * Versión inicial. 20 | 21 | ## Requisitos previos 22 | 23 | * Visual Studio 2015 o posterior. 24 | * Word 2016 para Windows, compilación 16.0.6727.1000 o posterior. 25 | 26 | ## Probar el complemento 27 | 28 | 1. Clone o descargue el proyecto en el escritorio. 29 | 2. Abra el archivo Word-Add-in-JavaScript-MDConversion.sln en Visual Studio. 30 | 2. Pulse F5. 31 | 3. Cuando se inicie Word, pulse el botón **Abrir convertidor** en la cinta de opciones **Inicio**. 32 | 4. Cuando se haya cargado la aplicación, pulse el botón **Insertar documento Markdown de prueba**. 33 | 5. Cuando se haya cargado el texto Markdown de ejemplo, pulse el botón **Convertir texto MD a Word**. 34 | 6. Después de convertir el documento a Word, edítelo. 35 | 7. Pulse el botón **Convertir documento a Markdown**. 36 | 8. Una vez que el documento se haya convertido, copie y pegue su contenido en un Controlador de vista previa de Markdown, como Visual Studio Code. 37 | 9. Como alternativa, puede empezar con el botón **Insertar documento de Word de prueba** y convertir a Markdown el documento de Word de ejemplo que se haya creado. 38 | 10. Si lo desea, empiece con su propio texto de Markdown o contenido de Word y pruebe el complemento. 39 | 40 | ## Problemas conocidos 41 | 42 | - Debido a un error en la forma en la que se generan las listas de Word creadas mediante programación, la conversión de Markdown a Word solo convertirá correctamente la primera lista (en ocasiones, las dos primeras) de un documento (todos los números de las listas Markdown se convertirán correctamente a Word). 43 | - Si convierte el mismo documento varias veces de Word a Markdown y viceversa, todas las filas de las tablas tomarán el formato de la fila de encabezado, que normalmente contiene texto en negrita. 44 | - El complemento utiliza algunas API de Office que no están admitidas todavía en Word Online (a partir de 15/2/2017). Debería probarlo en el escritorio de Word que se abre automáticamente cuando presiona F5. 45 | 46 | ## Preguntas y comentarios 47 | 48 | Nos encantaría recibir sus comentarios sobre este ejemplo. Puede enviarnos comentarios a través de la sección *Problemas* de este repositorio. 49 | 50 | Las preguntas generales sobre el desarrollo de Microsoft Office 365 deben publicarse en [Desbordamiento de pila](http://stackoverflow.com/questions/tagged/office-js+API). Si su pregunta trata sobre las API de JavaScript para Office, asegúrese de que su pregunta se etiqueta con [office-js] y [API]. 51 | 52 | ## Recursos adicionales 53 | 54 | * 55 | [Documentación de complementos de Office](https://msdn.microsoft.com/en-us/library/office/jj220060.aspx) 56 | * [Centro de desarrollo de Office](http://dev.office.com/) 57 | * Más ejemplos de complementos de Office en [OfficeDev en GitHub](https://github.com/officedev) 58 | 59 | ## Copyright 60 | Copyright (c) 2016 Microsoft Corporation. Todos los derechos reservados. 61 | 62 | 63 | 64 | Este proyecto ha adoptado el [Código de conducta de código abierto de Microsoft](https://opensource.microsoft.com/codeofconduct/). Para obtener más información, consulte las [preguntas más frecuentes sobre el Código de conducta](https://opensource.microsoft.com/codeofconduct/faq/) o póngase en contacto con [opencode@microsoft.com](mailto:opencode@microsoft.com) si tiene otras preguntas o comentarios. 65 | -------------------------------------------------------------------------------- /README-Localized/README-ru-ru.md: -------------------------------------------------------------------------------- 1 | # Надстройка Office, которая выполняет преобразование документа Word в документ Markdown и наоборот 2 | 3 | Используйте API-интерфейсы Word.js, чтобы преобразовать документ Markdown в документ Word для редактирования. Вы сможете выполнить обратное преобразование с помощью объектов Paragraph, Table, List и Range. 4 | 5 | ![Преобразование формата Word в формат Markdown и наоборот](../readme_art/ReadMeScreenshot.PNG) 6 | 7 | ## Содержание 8 | * [История изменений](#change-history) 9 | * [Необходимые компоненты](#prerequisites) 10 | * [Тестирование надстройки](#test-the-add-in) 11 | * [Известные проблемы](#known-issues) 12 | * [Вопросы и комментарии](#questions-and-comments) 13 | * [Дополнительные ресурсы](#additional-resources) 14 | 15 | ## История изменений 16 | 17 | 16 декабря 2016 г. 18 | 19 | * Исходная версия. 20 | 21 | ## Необходимые компоненты 22 | 23 | * Visual Studio 2015 или более поздней версии. 24 | * Word 2016 для Windows, сборка 16.0.6727.1000 или более новая. 25 | 26 | ## Тестирование надстройки 27 | 28 | 1. Клонируйте проект или скачайте его на компьютер. 29 | 2. Откройте файл Word-Add-in-JavaScript-MDConversion.sln в Visual Studio. 30 | 2. Нажмите клавишу F5. 31 | 3. Когда запустится Word, нажмите кнопку **Открыть преобразователь** на ленте **Главная**. 32 | 4. Когда приложение загрузится, нажмите кнопку **Insert test Markdown document** (Вставить тестовый документ Markdown). 33 | 5. Когда текст Markdown загрузится, нажмите кнопку **Convert MD text to Word** (Преобразовать текст MD в формат Word). 34 | 6. Когда документ будет преобразован в документ Word, отредактируйте его. 35 | 7. Нажмите кнопку **Convert document to Markdown** (Преобразовать документ в документ Markdown). 36 | 8. Когда документ будет преобразован, скопируйте и вставьте его содержимое в средство просмотра документов Markdown, такое как Visual Studio Code. 37 | 9. Кроме того, вы можете сначала нажать кнопку **Insert test Word document** (Вставить тестовый документ Word) и преобразовать созданный образец документа Word в документ Markdown. 38 | 10. При желании вы можете проверить надстройку, преобразовав свой текст Markdown или содержимое Word. 39 | 40 | ## Известные проблемы 41 | 42 | - Из-за ошибки, связанной с программным созданием списков Word, при преобразовании документа Markdown в документ Word правильно преобразуется только первый из списков (или иногда первые два). (Все списки Markdown правильно преобразуются в формат Word.) 43 | - Если один и тот же документ несколько раз преобразовать из Word в Markdown и наоборот, все строки в таблицах будут отформатированы так же, как и строки заголовков, для которых обычно используется полужирный шрифт. 44 | - Эта надстройка использует некоторые API Office, которые Word Online пока не поддерживает (по состоянию на 15.02.2017). Следует протестировать это в классической версии Word (открывается автоматически при нажатии клавиши F5). 45 | 46 | ## Вопросы и комментарии 47 | 48 | Мы будем рады узнать ваше мнение об этом примере. Своими мыслями можете поделиться на вкладке *Issues* (Проблемы) этого репозитория. 49 | 50 | Общие вопросы о разработке решений для Microsoft Office 365 следует задавать на сайте [Stack Overflow](http://stackoverflow.com/questions/tagged/office-js+API). Если ваш вопрос касается API JavaScript для Office, добавьте к нему теги [office-js] и [API]. 51 | 52 | ## Дополнительные ресурсы 53 | 54 | * 55 | [Документация по надстройкам Office](https://msdn.microsoft.com/en-us/library/office/jj220060.aspx) 56 | * [Центр разработки для Office](http://dev.office.com/) 57 | * Другие примеры надстроек Office см. на странице [OfficeDev на Github](https://github.com/officedev). 58 | 59 | ## Авторское право 60 | © Корпорация Майкрософт (Microsoft Corporation), 2016. Все права защищены. 61 | 62 | 63 | 64 | Этот проект соответствует [правилам поведения Майкрософт, касающимся обращения с открытым кодом](https://opensource.microsoft.com/codeofconduct/). Дополнительную информацию см. в разделе [часто задаваемых вопросов по правилам поведения](https://opensource.microsoft.com/codeofconduct/faq/). Если у вас возникли вопросы или замечания, напишите нам по адресу [opencode@microsoft.com](mailto:opencode@microsoft.com). 65 | -------------------------------------------------------------------------------- /README-Localized/README-fr-fr.md: -------------------------------------------------------------------------------- 1 | # Complément Office réalisant une conversion directement entre les formats Word et Markdown 2 | 3 | Utilisez les API Word.js pour convertir un document Markdown en Word afin de le modifier, puis pour convertir le document Word au format Markdown, en utilisant les objets Paragraphe, Tableau, Liste et Plage. 4 | 5 | ![Conversion entre Word et Markdown](../readme_art/ReadMeScreenshot.PNG) 6 | 7 | ## Sommaire 8 | * [Historique des modifications](#change-history) 9 | * [Conditions préalables](#prerequisites) 10 | * [Test du complément](#test-the-add-in) 11 | * [Problèmes connus](#known-issues) 12 | * [Questions et commentaires](#questions-and-comments) 13 | * [Ressources supplémentaires](#additional-resources) 14 | 15 | ## Historique des modifications 16 | 17 | 16 décembre 2016 : 18 | 19 | * Version d’origine. 20 | 21 | ## Conditions préalables 22 | 23 | * Visual Studio 2015 ou version ultérieure. 24 | * Word 2016 pour Windows, version 16.0.6727.1000 ou ultérieure. 25 | 26 | ## Test du complément 27 | 28 | 1. Clonez ou téléchargez le projet sur votre ordinateur. 29 | 2. Ouvrez le fichier Word-Add-in-JavaScript-MDConversion.sln dans Visual Studio. 30 | 2. Appuyez sur la touche F5. 31 | 3. Une fois Word démarré, appuyez sur le bouton **Ouvrir le convertisseur** situé sur le ruban **Accueil**. 32 | 4. Si l’application a chargé, appuyez sur le bouton **Insérer un document Markdown test**. 33 | 5. Après le chargement du texte Markdown d’exemple, appuyez sur le bouton **Convertir le texte MD en Word**. 34 | 6. Une fois que le document a été converti en Word, modifiez-le. 35 | 7. Appuyez sur le bouton **Convertir le document au format Markdown**. 36 | 8. Après que le document a été converti, copiez et collez son contenu dans un générateur d’aperçu Markdown, tel que Visual Studio Code. 37 | 9. Par ailleurs, vous pouvez commencer avec le bouton **Insérer un document Word test** et convertir le document Word d’exemple qui a été créé au format Markdown. 38 | 10. Vous pouvez également commencer par un de vos textes Markdown ou contenus Word, et tester le complément. 39 | 40 | ## Problèmes connus 41 | 42 | - En raison d’un bogue lors de la création des listes Word créées par programme, la conversion du format Markdown en Word fonctionnera correctement uniquement pour la première liste (ou parfois les deux premières listes) dans un document. (De nombreuses listes Markdown seront converties correctement en Word.) 43 | - Si vous convertissez le même document à plusieurs reprises entre Word et Markdown, dans un sens et dans l’autre, toutes les lignes des tableaux adopteront la mise en forme de la ligne d’en-tête, qui comprend généralement du texte en gras. 44 | - Le complément utilise des API Office qui ne sont pas encore prises en charge dans Word Online (à compter du 15/02/2017). Vous devez le tester dans l’application de bureau Word (qui s’ouvre automatiquement lorsque vous appuyez sur F5). 45 | 46 | ## Questions et commentaires 47 | 48 | Nous serions ravis de connaître votre opinion sur cet exemple. Vous pouvez nous envoyer vos commentaires via la section *Problèmes* de ce référentiel. 49 | 50 | Les questions générales sur le développement de Microsoft Office 365 doivent être publiées sur [Stack Overflow](http://stackoverflow.com/questions/tagged/office-js+API). Si votre question concerne les API Office JavaScript, assurez-vous qu’elle est marquée avec les balises [office js] et [API]. 51 | 52 | ## Ressources supplémentaires 53 | 54 | * 55 | [Documentation de complément Office](https://msdn.microsoft.com/en-us/library/office/jj220060.aspx) 56 | * [Centre de développement Office](http://dev.office.com/) 57 | * Plus d’exemples de complément Office sur [OfficeDev sur Github](https://github.com/officedev) 58 | 59 | ## Copyright 60 | Copyright (c) 2016 Microsoft Corporation. Tous droits réservés. 61 | 62 | 63 | 64 | Ce projet a adopté le [code de conduite Open Source de Microsoft](https://opensource.microsoft.com/codeofconduct/). Pour plus d’informations, reportez-vous à la [FAQ relative au code de conduite](https://opensource.microsoft.com/codeofconduct/faq/) ou contactez [opencode@microsoft.com](mailto:opencode@microsoft.com) pour toute question ou tout commentaire. 65 | -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | #Contribute to this code sample 2 | 3 | Thank you for your interest in this sample! Your contributions and improvements will help the developer community. 4 | 5 | ##Ways to contribute 6 | 7 | There are several ways you can contribute to this sample: providing better code comments, fixing open issues, and adding new features. 8 | 9 | ###Provide better code comments 10 | 11 | Code comments make code samples even better by helping developers learn to use the code correctly in their own applications. If you spot a class, method, or section of code that you think could use better descriptions, then create a pull request with your code comments. 12 | 13 | 14 | In general we want our code comments to follow these guidelines: 15 | 16 | - Any code that has associated documentation displayed in an IDE (such as IntelliSense, or JavaDocs) has code comments. 17 | - Classes, methods, parameters, and return values have clear descriptions. 18 | - Exceptions and errors are documented. 19 | - Remarks exist for anything special or notable about the code. 20 | - Sections of code that have complex algorithms have appropriate comments describing what they do. 21 | - Code added from Stack Overflow, or any other source, is clearly attributed. 22 | 23 | ###Fix open issues 24 | 25 | Sometimes we get a lot of issues, and it can be hard to keep up. If you have a solution to an open issue that hasn't been addressed, fix the issue and then submit a pull request. 26 | 27 | ###Add a new feature 28 | 29 | New features are great! Be sure to check with the repository admin first to be sure the feature will fit the intent of the sample. Start by opening an issue in the repository that proposes and describes the feature. The repository admin will respond and may ask for more information. If the admin agrees to the new feature, create the feature and submit a pull request. 30 | 31 | ##Contribution guidelines 32 | 33 | We have some guidelines to help maintain a healthy repo and code for everyone. 34 | 35 | ###The Contribution License Agreement 36 | 37 | For most contributions, you'll be asked to sign a Contribution License Agreement (CLA). This will happen when you submit a pull request. Microsoft will send a link to the CLA to sign via email. Once you sign the CLA, your pull request can proceed. Read the CLA carefully, because you may need to have your employer sign it. 38 | 39 | ###Code contribution checklist 40 | 41 | Be sure to satisfy all of the requirements in the following list before submitting a pull request: 42 | 43 | - Follow the code style that is appropriate for the platform and language in this repo. For example, Android code follows the style conventions found in the [Code Style for Contributors guide](https://source.android.com/source/code-style.html). 44 | - Test your code. 45 | - Test the UI thoroughly to be sure nothing has been broken by your change. 46 | - Keep the size of your code change reasonable. if the repository owner cannot review your code change in 4 hours or less, your pull request may not be reviewed and approved quickly. 47 | - Avoid unnecessary changes. The reviewer will check differences between your code and the original code. Whitespace changes are called out along with your code. Be sure your changes will help improve the content. 48 | 49 | ###Submit a pull request to the master branch 50 | 51 | When you're finished with your work and are ready to have it merged into the master repository, follow these steps. Note: pull requests are typically reviewed within 10 business days. If your pull request is accepted you will be credited for your submission. 52 | 53 | 1. Submit your pull request against the master branch. 54 | 2. Sign the CLA, if you haven't already done so. 55 | 3. One of the repo admins will process your pull request, including performing a code review. If there are questions, discussions, or change requests in the pull request, be sure to respond. 56 | 4. When the repo admins are satisfied, they will accept and merge the pull request. 57 | 58 | Congratulations, you have successfully contributed to the sample! 59 | 60 | ##FAQ 61 | 62 | ###Where do I get a Contributor's License Agreement? 63 | 64 | You will automatically be sent a notice that you need to sign the Contributor's License Agreement (CLA) if your pull request requires one. 65 | 66 | As a community member, you must sign the CLA before you can contribute large submissions to this project. You only need complete and submit the CLA document once. Carefully review the document. You may be required to have your employer sign the document. 67 | 68 | ###What happens with my contributions? 69 | 70 | When you submit your changes, via a pull request, our team will be notified and will review your pull request. You will receive notifications about your pull request from GitHub; you may also be notified by someone from our team if we need more information. We reserve the right to edit your submission for legal, style, clarity, or other issues. 71 | 72 | ###Who approves pull requests? 73 | 74 | The admin of the repository approves pull requests. 75 | 76 | ###How soon will I get a response about my change request or issue? 77 | 78 | We typically review pull requests and respond to issues within 10 business days. 79 | 80 | ##More resources 81 | 82 | - To learn more about Markdown, see [Daring Fireball](http://daringfireball.net/). 83 | - To learn more about using Git and GitHub, check out the [GitHub Help section](http://help.github.com/). 84 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Scripts/FabricUI/message.banner.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information. 2 | 3 | (function () { 4 | "use strict"; 5 | 6 | var FabricComponents = window.FabricComponents || {}; 7 | // app.notification = {}; 8 | 9 | $(document).ready(function () { 10 | /** 11 | * Define the MessageBanner constructor 12 | * @param {HTMLElement} container - the target container for an instance of MessageBanner 13 | * @constructor 14 | */ 15 | FabricComponents.MessageBanner = function (container) { 16 | this.container = container; 17 | this.init(); 18 | }; 19 | 20 | FabricComponents.MessageBanner.prototype = CreatePrototype(); 21 | 22 | // Create a MessageBanner components for every element in 23 | // the page that is styled as a MessageBanner. 24 | $('.ms-MessageBanner').each(function () { 25 | new FabricComponents.MessageBanner(this); 26 | }); 27 | 28 | 29 | function CreatePrototype() { 30 | 31 | var _clipper; 32 | var _bufferSize; 33 | var _textContainerMaxWidth = 700; 34 | var _clientWidth; 35 | var _textWidth; 36 | var _initTextWidth; 37 | var _chevronButton; 38 | var _errorBanner; 39 | var _closeButton; 40 | var _bufferElementsWidth = 88; 41 | var _bufferElementsWidthSmall = 35; 42 | var SMALL_BREAK_POINT = 480; 43 | 44 | /** 45 | * sets styles on resize 46 | */ 47 | var _onResize = function () { 48 | _clientWidth = _errorBanner.offsetWidth; 49 | if (window.innerWidth >= SMALL_BREAK_POINT) { 50 | _resizeRegular(); 51 | } else { 52 | _resizeSmall(); 53 | } 54 | }; 55 | 56 | /** 57 | * resize above 480 pixel breakpoint 58 | */ 59 | var _resizeRegular = function () { 60 | if ((_clientWidth - _bufferSize) > _initTextWidth && _initTextWidth < _textContainerMaxWidth) { 61 | _textWidth = "auto"; 62 | _chevronButton.className = "ms-MessageBanner-expand"; 63 | _collapse(); 64 | } else { 65 | _textWidth = Math.min((_clientWidth - _bufferSize), _textContainerMaxWidth) + "px"; 66 | if (_chevronButton.className.indexOf("is-visible") === -1) { 67 | _chevronButton.className += " is-visible"; 68 | } 69 | } 70 | _clipper.style.width = _textWidth; 71 | }; 72 | 73 | /** 74 | * resize below 480 pixel breakpoint 75 | */ 76 | var _resizeSmall = function () { 77 | if (_clientWidth - (_bufferElementsWidthSmall + _closeButton.offsetWidth) > _initTextWidth) { 78 | _textWidth = "auto"; 79 | _collapse(); 80 | } else { 81 | _textWidth = (_clientWidth - (_bufferElementsWidthSmall + _closeButton.offsetWidth)) + "px"; 82 | } 83 | _clipper.style.width = _textWidth; 84 | }; 85 | /** 86 | * caches elements and values of the component 87 | */ 88 | var _cacheDOM = function (context) { 89 | _errorBanner = context.container; 90 | _clipper = context.container.querySelector('.ms-MessageBanner-clipper'); 91 | _chevronButton = context.container.querySelector('.ms-MessageBanner-expand'); 92 | _bufferSize = _bufferElementsWidth; 93 | _closeButton = context.container.querySelector('.ms-MessageBanner-close'); 94 | }; 95 | 96 | /** 97 | * expands component to show full error message 98 | */ 99 | var _expand = function () { 100 | var icon = _chevronButton.querySelector('.ms-Icon'); 101 | _errorBanner.className += " is-expanded"; 102 | icon.className = "ms-Icon ms-Icon--chevronsUp"; 103 | }; 104 | 105 | /** 106 | * collapses component to only show truncated message 107 | */ 108 | var _collapse = function () { 109 | var icon = _chevronButton.querySelector('.ms-Icon'); 110 | _errorBanner.className = "ms-MessageBanner"; 111 | icon.className = "ms-Icon ms-Icon--chevronsDown"; 112 | }; 113 | 114 | var _toggleExpansion = function () { 115 | if (_errorBanner.className.indexOf("is-expanded") > -1) { 116 | _collapse(); 117 | } else { 118 | _expand(); 119 | } 120 | }; 121 | 122 | /** 123 | * hides banner when close button is clicked 124 | */ 125 | var _hideBanner = function () { 126 | if (_errorBanner.className.indexOf("hide") === -1) { 127 | _errorBanner.className += " hide"; 128 | setTimeout(function () { 129 | _errorBanner.className = "ms-MessageBanner is-hidden"; 130 | }, 500); 131 | } 132 | }; 133 | 134 | /** 135 | * shows banner if the banner is hidden 136 | */ 137 | var _showBanner = function () { 138 | _errorBanner.className = "ms-MessageBanner"; 139 | }; 140 | 141 | /** 142 | * sets handlers for resize and button click events 143 | */ 144 | var _setListeners = function () { 145 | window.addEventListener('resize', _onResize, false); 146 | _chevronButton.addEventListener("click", _toggleExpansion, false); 147 | _closeButton.addEventListener("click", _hideBanner, false); 148 | }; 149 | 150 | /** 151 | * initializes component 152 | */ 153 | var init = function () { 154 | _cacheDOM(this); 155 | _setListeners(); 156 | _clientWidth = _errorBanner.offsetWidth; 157 | _initTextWidth = _clipper.offsetWidth; 158 | _onResize(null); 159 | }; 160 | 161 | return { 162 | init: init, 163 | showBanner: _showBanner, 164 | hideBanner: _hideBanner, 165 | toggleExpansion: _toggleExpansion 166 | }; 167 | }; 168 | }); 169 | window.FabricComponents = FabricComponents; 170 | })(); -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversion/Word-Add-in-JavaScript-MDConversionManifest/Word-Add-in-JavaScript-MDConversion.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 11 | 12 | 13 | 14 | 15 | f38bbdc9-7de1-424d-a3c1-c8845cd455fe 16 | 17 | 18 | 1.0.0.0 19 | Microsoft Office Developer Education 20 | en-US 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | ReadWriteDocument 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | <!-- Description of the Getting Started callout. resid points to a LongString resource --> 58 | <Description resid="Contoso.GetStarted.Description"/> 59 | 60 | <!-- Point to a url resource which details how the add-in should be used. --> 61 | <LearnMoreUrl resid="Contoso.GetStarted.LearnMoreUrl"/> 62 | </GetStarted> 63 | 64 | <!-- PrimaryCommandSurface is the main Office Ribbon. --> 65 | <ExtensionPoint xsi:type="PrimaryCommandSurface"> 66 | <!-- Use OfficeTab to extend an existing Tab. Use CustomTab to create a new tab. --> 67 | <OfficeTab id="TabHome"> 68 | <!-- Ensure you provide a unique id for the group. Recommendation for any IDs is to namespace using your company name. --> 69 | <Group id="Contoso.Group1"> 70 | <!-- Label for your group. resid must point to a ShortString resource. --> 71 | <Label resid="Contoso.Conversion" /> 72 | <!-- Icons. Required sizes 16,32,80, optional 20, 24, 40, 48, 64. Strongly recommended to provide all sizes for great UX. --> 73 | <!-- Use PNG icons. All URLs on the resources section must use HTTPS. --> 74 | <Icon> 75 | <bt:Image size="16" resid="Contoso.tpicon_16x16" /> 76 | <bt:Image size="32" resid="Contoso.tpicon_32x32" /> 77 | <bt:Image size="80" resid="Contoso.tpicon_80x80" /> 78 | </Icon> 79 | 80 | <!-- Control. It can be of type "Button" or "Menu". --> 81 | <Control xsi:type="Button" id="Contoso.TaskpaneButton"> 82 | <Label resid="Contoso.TaskpaneButton.Label" /> 83 | <Supertip> 84 | <!-- ToolTip title. resid must point to a ShortString resource. --> 85 | <Title resid="Contoso.TaskpaneButton.Label" /> 86 | <!-- ToolTip description. resid must point to a LongString resource. --> 87 | <Description resid="Contoso.TaskpaneButton.Tooltip" /> 88 | </Supertip> 89 | <Icon> 90 | <bt:Image size="16" resid="Contoso.tpicon_16x16" /> 91 | <bt:Image size="32" resid="Contoso.tpicon_32x32" /> 92 | <bt:Image size="80" resid="Contoso.tpicon_80x80" /> 93 | </Icon> 94 | 95 | <!-- This is what happens when the command is triggered (E.g. click on the Ribbon). Supported actions are ExecuteFunction or ShowTaskpane. --> 96 | <Action xsi:type="ShowTaskpane"> 97 | <TaskpaneId>ButtonId1</TaskpaneId> 98 | <!-- Provide a url resource id for the location that will be displayed on the task pane. --> 99 | <SourceLocation resid="Contoso.Taskpane.Url" /> 100 | </Action> 101 | </Control> 102 | </Group> 103 | </OfficeTab> 104 | </ExtensionPoint> 105 | </DesktopFormFactor> 106 | </Host> 107 | </Hosts> 108 | 109 | <!-- You can use resources across hosts and form factors. --> 110 | <Resources> 111 | <bt:Images> 112 | <bt:Image id="Contoso.tpicon_16x16" DefaultValue="~remoteAppUrl/Images/taskpane_16x.png" /> 113 | <bt:Image id="Contoso.tpicon_32x32" DefaultValue="~remoteAppUrl/Images/taskpane_32x.png" /> 114 | <bt:Image id="Contoso.tpicon_80x80" DefaultValue="~remoteAppUrl/Images/taskpane_80x.png" /> 115 | </bt:Images> 116 | <bt:Urls> 117 | <bt:Url id="Contoso.Taskpane.Url" DefaultValue="~remoteAppUrl/Home.html" /> 118 | <bt:Url id="Contoso.GetStarted.LearnMoreUrl" DefaultValue="https://go.microsoft.com/fwlink/?LinkId=276812" /> 119 | </bt:Urls> 120 | <!-- ShortStrings max characters==125. --> 121 | <bt:ShortStrings> 122 | <bt:String id="Contoso.TaskpaneButton.Label" DefaultValue="Open Converter" /> 123 | <bt:String id="Contoso.Conversion" DefaultValue="Conversion" /> 124 | <bt:String id="Contoso.GetStarted.Title" DefaultValue="Start converting between Word and Markdown!" /> 125 | </bt:ShortStrings> 126 | <!-- LongStrings max characters==250. --> 127 | <bt:LongStrings> 128 | <bt:String id="Contoso.TaskpaneButton.Tooltip" DefaultValue="Click to open the converter" /> 129 | <bt:String id="Contoso.GetStarted.Description" DefaultValue="Your sample add-in loaded succesfully. Go to the HOME tab and click the 'Open Converter' button to get started." /> 130 | </bt:LongStrings> 131 | </Resources> 132 | </VersionOverrides> 133 | <!-- End Add-in Commands Mode integration. --> 134 | 135 | </OfficeApp> 136 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Word-Add-in-JavaScript-MDConversionWeb.csproj: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3 | <Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" /> 4 | <Import Project="..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" /> 5 | <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> 6 | <PropertyGroup> 7 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> 8 | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> 9 | <ProductVersion> 10 | </ProductVersion> 11 | <SchemaVersion>2.0</SchemaVersion> 12 | <ProjectGuid>{D046B860-A41D-44B6-9088-D7B356C21450}</ProjectGuid> 13 | <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids> 14 | <OutputType>Library</OutputType> 15 | <AppDesignerFolder>Properties</AppDesignerFolder> 16 | <RootNamespace>Word_Add_in_JavaScript_MDConversionWeb</RootNamespace> 17 | <AssemblyName>Word-Add-in-JavaScript-MDConversionWeb</AssemblyName> 18 | <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> 19 | <UseIISExpress>true</UseIISExpress> 20 | <IISExpressSSLPort>44356</IISExpressSSLPort> 21 | <IISExpressAnonymousAuthentication /> 22 | <IISExpressWindowsAuthentication /> 23 | <IISExpressUseClassicPipelineMode /> 24 | <UseGlobalApplicationHostFile /> 25 | <NuGetPackageImportStamp> 26 | </NuGetPackageImportStamp> 27 | <TargetOfficeVersion>15.0</TargetOfficeVersion> 28 | </PropertyGroup> 29 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> 30 | <DebugSymbols>true</DebugSymbols> 31 | <DebugType>full</DebugType> 32 | <Optimize>false</Optimize> 33 | <OutputPath>bin\</OutputPath> 34 | <DefineConstants>DEBUG;TRACE</DefineConstants> 35 | <ErrorReport>prompt</ErrorReport> 36 | <WarningLevel>4</WarningLevel> 37 | </PropertyGroup> 38 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> 39 | <DebugType>pdbonly</DebugType> 40 | <Optimize>true</Optimize> 41 | <OutputPath>bin\</OutputPath> 42 | <DefineConstants>TRACE</DefineConstants> 43 | <ErrorReport>prompt</ErrorReport> 44 | <WarningLevel>4</WarningLevel> 45 | </PropertyGroup> 46 | <ItemGroup> 47 | <Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 48 | <HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath> 49 | <Private>True</Private> 50 | </Reference> 51 | <Reference Include="Microsoft.CSharp" /> 52 | <Reference Include="System.Web.DynamicData" /> 53 | <Reference Include="System.Web.Entity" /> 54 | <Reference Include="System.Web.ApplicationServices" /> 55 | <Reference Include="System.ComponentModel.DataAnnotations" /> 56 | <Reference Include="System" /> 57 | <Reference Include="System.Data" /> 58 | <Reference Include="System.Core" /> 59 | <Reference Include="System.Data.DataSetExtensions" /> 60 | <Reference Include="System.Web.Extensions" /> 61 | <Reference Include="System.Xml.Linq" /> 62 | <Reference Include="System.Drawing" /> 63 | <Reference Include="System.Web" /> 64 | <Reference Include="System.Xml" /> 65 | <Reference Include="System.Configuration" /> 66 | <Reference Include="System.Web.Services" /> 67 | <Reference Include="System.EnterpriseServices" /> 68 | </ItemGroup> 69 | <ItemGroup> 70 | <Content Include="Images\logo-filled.png" /> 71 | <Content Include="Images\taskpane_16x.png" /> 72 | <Content Include="Images\taskpane_32x.png" /> 73 | <Content Include="Images\taskpane_80x.png" /> 74 | <None Include="Web.Debug.config"> 75 | <DependentUpon>Web.config</DependentUpon> 76 | </None> 77 | <None Include="Web.Release.config"> 78 | <DependentUpon>Web.config</DependentUpon> 79 | </None> 80 | </ItemGroup> 81 | <ItemGroup> 82 | <Content Include="Content\message.banner.css" /> 83 | <Content Include="Home.css" /> 84 | <Content Include="Home.html" /> 85 | <Content Include="Home.js" /> 86 | <Content Include="Images\AddinIcon.png" /> 87 | <Content Include="Images\Close.png" /> 88 | <Content Include="SampleContent.js" /> 89 | <Content Include="Scripts\FabricUI\message.banner.js" /> 90 | <None Include="Scripts\_references.js" /> 91 | <Content Include="Scripts\_officeintellisense.js" /> 92 | <Content Include="Web.config" /> 93 | </ItemGroup> 94 | <ItemGroup> 95 | <Compile Include="Properties\AssemblyInfo.cs" /> 96 | </ItemGroup> 97 | <PropertyGroup> 98 | <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> 99 | <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> 100 | </PropertyGroup> 101 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> 102 | <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" /> 103 | <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" /> 104 | <ProjectExtensions> 105 | <VisualStudio> 106 | <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> 107 | <WebProjectProperties> 108 | <UseIIS>True</UseIIS> 109 | <AutoAssignPort>True</AutoAssignPort> 110 | <DevelopmentServerPort>1124</DevelopmentServerPort> 111 | <DevelopmentServerVPath>/</DevelopmentServerVPath> 112 | <IISUrl>http://localhost:1124/</IISUrl> 113 | <NTLMAuthentication>False</NTLMAuthentication> 114 | <UseCustomServer>False</UseCustomServer> 115 | <CustomServerUrl> 116 | </CustomServerUrl> 117 | <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile> 118 | </WebProjectProperties> 119 | </FlavorProperties> 120 | </VisualStudio> 121 | </ProjectExtensions> 122 | <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> 123 | <PropertyGroup> 124 | <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> 125 | </PropertyGroup> 126 | <Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props'))" /> 127 | <Error Condition="!Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" /> 128 | </Target> 129 | <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 130 | Other similar extension points exist, see Microsoft.Common.targets. 131 | <Target Name="BeforeBuild"> 132 | </Target> 133 | <Target Name="AfterBuild"> 134 | </Target> 135 | --> 136 | </Project> -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Content/message.banner.css: -------------------------------------------------------------------------------- 1 | /* Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See full license in root of repo. */ 2 | html, body { 3 | width: 100%; 4 | height: 100%; 5 | margin: 0; 6 | padding: 0; 7 | overflow: auto; } 8 | 9 | body { 10 | position: relative; 11 | font-size: 16px; } 12 | 13 | main { 14 | height: 100%; 15 | overflow-y: auto; } 16 | 17 | footer { 18 | width: 100%; 19 | position: relative; 20 | bottom: 0; } 21 | 22 | ul { 23 | padding: 0; } 24 | 25 | .clearfix { 26 | display: block; 27 | clear: both; 28 | height: 0; } 29 | 30 | .pointerCursor { 31 | cursor: pointer; } 32 | 33 | .invisible { 34 | visibility: hidden; } 35 | 36 | .undisplayed { 37 | display: none; } 38 | 39 | .ms-Icon.enlarge { 40 | position: relative; 41 | font-size: 20px; 42 | top: 4px; } 43 | 44 | .ms-notification-message-banner { 45 | display: -webkit-flex; 46 | display: flex; 47 | -webkit-flex-direction: column; 48 | flex-direction: column; 49 | -webkit-flex-wrap: nowrap; 50 | flex-wrap: nowrap; 51 | height: 100%; } 52 | .ms-notification-message-banner__main { 53 | display: -webkit-flex; 54 | display: flex; 55 | -webkit-flex-direction: column; 56 | flex-direction: column; 57 | -webkit-flex-wrap: nowrap; 58 | flex-wrap: nowrap; 59 | -webkit-flex: 1 1 0; 60 | flex: 1 1 0; 61 | height: 100%; } 62 | .ms-notification-message-banner__header { 63 | border-bottom: solid 2px #0078d7; 64 | display: -webkit-inline-flex; 65 | display: inline-flex; 66 | -webkit-justify-content: center; 67 | justify-content: center; 68 | -webkit-align-items: center; 69 | align-items: center; } 70 | .ms-notification-message-banner__header--left { 71 | transition: background ease 0.1s, color ease 0.1s; 72 | padding: 8px 20px; 73 | cursor: pointer; } 74 | .ms-notification-message-banner__header--left:active, .ms-notification-message-banner__header--left:hover { 75 | background: #eff6fc; 76 | cursor: pointer; } 77 | .ms-notification-message-banner__header--left:active { 78 | background: #eff6fc; 79 | -webkit-transform: scale3d(0.98, 0.98, 1); 80 | transform: scale3d(0.98, 0.98, 1); } 81 | .ms-notification-message-banner__header--left--disabled { 82 | opacity: 0.6; 83 | pointer-events: none; 84 | cursor: not-allowed; } 85 | .ms-notification-message-banner__header--left--disabled:active, .ms-notification-message-banner__header--left--disabled:hover { 86 | background: transparent; } 87 | .ms-notification-message-banner__header--left--disabled:active { 88 | -webkit-transform: none; 89 | transform: none; } 90 | .ms-notification-message-banner__header--right { 91 | -webkit-flex: 1 0 0px; 92 | flex: 1 0 0px; 93 | display: -webkit-inline-flex; 94 | display: inline-flex; 95 | -webkit-justify-content: center; 96 | justify-content: center; 97 | -webkit-align-items: center; 98 | align-items: center; } 99 | .ms-notification-message-banner__header--right p { 100 | padding: 0 10px; 101 | -webkit-flex: 1 0 0px; 102 | flex: 1 0 0px; 103 | overflow: hidden; 104 | white-space: nowrap; 105 | text-overflow: ellipsis; 106 | text-align: center; 107 | cursor: pointer; 108 | padding: 10px 20px; 109 | transition: background ease 0.1s, color ease 0.1s; } 110 | .ms-notification-message-banner__header--right p:active, .ms-notification-message-banner__header--right p:hover { 111 | background: #eff6fc; 112 | cursor: pointer; } 113 | .ms-notification-message-banner__header--right p:active { 114 | background: #eff6fc; 115 | -webkit-transform: scale3d(0.98, 0.98, 1); 116 | transform: scale3d(0.98, 0.98, 1); } 117 | .ms-notification-message-banner__header--right p--disabled { 118 | opacity: 0.6; 119 | pointer-events: none; 120 | cursor: not-allowed; } 121 | .ms-notification-message-banner__header--right p--disabled:active, .ms-notification-message-banner__header--right p--disabled:hover { 122 | background: transparent; } 123 | .ms-notification-message-banner__header--right p--disabled:active { 124 | -webkit-transform: none; 125 | transform: none; } 126 | .ms-notification-message-banner__header--right p:last-child { 127 | border-right: none; } 128 | .ms-notification-message-banner__header--selected { 129 | background-color: #daeaf8; } 130 | .ms-notification-message-banner__content { 131 | display: -webkit-flex; 132 | display: flex; 133 | -webkit-flex-direction: column; 134 | flex-direction: column; 135 | -webkit-flex-wrap: nowrap; 136 | flex-wrap: nowrap; 137 | height: 100%; 138 | -webkit-flex: 1 1 0; 139 | flex: 1 1 0; 140 | min-height: 180px; 141 | padding: 20px; } 142 | .ms-notification-message-banner__content h2 { 143 | margin-bottom: 20px; } 144 | .ms-notification-message-banner__content__title, .ms-notification-message-banner__content__subtitle, .ms-notification-message-banner__content__text { 145 | margin-bottom: 20px; } 146 | .ms-notification-message-banner__input { 147 | padding-bottom: 50px; 148 | margin-top: 10px; 149 | width: 100%; } 150 | .ms-notification-message-banner__input label { 151 | clear: both; 152 | display: block; 153 | width: 100%; 154 | margin-bottom: 5px; } 155 | .ms-notification-message-banner__input input { 156 | width: calc(100% - 24px); 157 | border-style: solid; 158 | border-width: 1px; 159 | padding: 10px; 160 | margin-bottom: 4px; } 161 | .ms-notification-message-banner__input span { 162 | padding-right: 10px; 163 | padding-left: 10px; } 164 | .ms-notification-message-banner__footer { 165 | display: -webkit-inline-flex; 166 | display: inline-flex; 167 | -webkit-justify-content: center; 168 | justify-content: center; 169 | -webkit-align-items: center; 170 | align-items: center; } 171 | .ms-notification-message-banner__footer--left { 172 | transition: background ease 0.1s, color ease 0.1s; 173 | display: -webkit-inline-flex; 174 | display: inline-flex; 175 | -webkit-justify-content: flex-start; 176 | justify-content: flex-start; 177 | -webkit-align-items: center; 178 | align-items: center; 179 | -webkit-flex: 1 0 0px; 180 | flex: 1 0 0px; 181 | padding: 20px; } 182 | .ms-notification-message-banner__footer--left:active, .ms-notification-message-banner__footer--left:hover { 183 | background: #005ca4; 184 | cursor: pointer; } 185 | .ms-notification-message-banner__footer--left:active { 186 | background: #005ca4; } 187 | .ms-notification-message-banner__footer--left--disabled { 188 | opacity: 0.6; 189 | pointer-events: none; 190 | cursor: not-allowed; } 191 | .ms-notification-message-banner__footer--left--disabled:active, .ms-notification-message-banner__footer--left--disabled:hover { 192 | background: transparent; } 193 | .ms-notification-message-banner__footer--left img { 194 | width: 40px; 195 | height: 40px; } 196 | .ms-notification-message-banner__footer--left h1 { 197 | -webkit-flex: 1 0 0px; 198 | flex: 1 0 0px; 199 | margin-left: 15px; 200 | text-align: left; 201 | width: auto; 202 | max-width: auto; 203 | overflow: hidden; 204 | white-space: nowrap; 205 | text-overflow: ellipsis; } 206 | .ms-notification-message-banner__footer--right { 207 | transition: background ease 0.1s, color ease 0.1s; 208 | padding: 29px 20px; } 209 | .ms-notification-message-banner__footer--right:active, .ms-notification-message-banner__footer--right:hover { 210 | background: #005ca4; 211 | cursor: pointer; } 212 | .ms-notification-message-banner__footer--right:active { 213 | background: #005ca4; } 214 | .ms-notification-message-banner__footer--right--disabled { 215 | opacity: 0.6; 216 | pointer-events: none; 217 | cursor: not-allowed; } 218 | .ms-notification-message-banner__footer--right--disabled:active, .ms-notification-message-banner__footer--right--disabled:hover { 219 | background: transparent; } 220 | 221 | @media screen and (max-width: 479px) { 222 | .ms-MessageBanner-text { 223 | margin-left: 20px; 224 | margin-right: 20px; 225 | padding: 18px 0; 226 | min-width: 240px; } } 227 | 228 | .ms-MessageBanner.is-expanded { 229 | height: auto; 230 | overflow: inherit; } 231 | 232 | .ms-MessageBanner-button-white { 233 | color: white; } 234 | -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/SampleContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | (function () { 7 | "use strict"; 8 | 9 | var WordMarkdownConversion = window.WordMarkdownConversion || {}; 10 | 11 | // Value is a base 64 encoding of a sample Word docx file. 12 | WordMarkdownConversion.sampleWordDocument = "UEsDBBQABgAIAAAAIQAo2FMQhwEAAJQGAAATAAgCW0NvbnRlbnRfVHlwZXNdLnhtbCCiBAIooAAC AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0 lctuwjAQRfeV+g+RtxUxdFFVFYFFH8sWqfQDjDOBCL/kMa+/7yQhEapoQilsIjkz957rSeIMx1ut ojV4zK1J2CDuswiMtGlu5gn7mr71HlmEQZhUKGsgYTtANh7d3gynOwcYkdpgwhYhuCfOUS5AC4yt A0OVzHotAi39nDshl2IO/L7ff+DSmgAm9ELhwUbDF8jESoXodUu3qyQeFLLouWosWAkTzqlcikB1 vjbpD0pvT4hJWfbgInd4Rw2MHyUUld8Be90HjcbnKUQT4cO70NTFN9anPLVypUkZt9scyWmzLJfQ 6As3560ERJq5VnFT0SI3df5fc5iVnoEn5eWDNNadITDsFODlE1S+3XgIgQTXCLB37oywgdnn1VIc mHcGyYg7FTMFl4/RWJ8yDag/NORB4NIJc9ILousYxaYbj8bhj+TD1eBseic00KkH1fUUSvvYS5s2 JHVOvHVIp6g/4ynXx2Sh7tHzdeBD3j7ZhkjW/95fOdYU0iNsXv5TRt8AAAD//wMAUEsDBBQABgAI AAAAIQAPZU49FgEAAOUCAAALAAgCX3JlbHMvLnJlbHMgogQCKKAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArJLdSgMxEIXvBd8h5L6b3Soi 0t3eiNA7kfUBxmT2h24yIRlt+/am9YduqYuglzNz5vDNSRbLrR3EG4bYkytlkeVSoNNketeW8rl+ mN1KERmcgYEclnKHUS6ry4vFEw7AaSl2vY8iubhYyo7Z3ykVdYcWYkYeXZo0FCxwKkOrPOg1tKjm eX6jwrGHrEaeYmVKGVbmSop65/Fv3soigwEGpSngzIe0HbhPt4gaQotcSkP6MbXjQZElZ6nOA81/ ALK9DhSp4UyTVdQ0vd6jFMUJygZfcMvo9okzxLUHd8yxoWBGmqi+VVNYxe9z+mC7J/1q0fG5uMaK Ezjz2Z6iuf5PmkMUBs30u4H3X0Rq9DmrdwAAAP//AwBQSwMEFAAGAAgAAAAhABQ+vpxJAQAAgQQA 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 AAAAAA8ADwD6AwAAzTwAAAAA"; 13 | 14 | // Value is an MD document with line breaks and quotation marks escaped. 15 | WordMarkdownConversion.sampleMDDocument = "# A Sample Document (first level header)\n\nThis document has it all; **bolded** text, *italicized* text, bookmark links, a web link, a table, a code block, and a very complicated list.\n\nThis is another paragraph, because you can't have *too* many.\n\n## Table of Contents with Bookmark Links\n\n[Table](#table-second-level-header) \n\n[Code Block](#code-block-fourth-level-header) \n\n[Paragraph with Web Link](#paragraph-with-web-link-third-level-header) \n\n[Complex List](#complex-list-fifth-level-header) \n\n## Table (second level header)\n\n| Name | Mood | Hobby | \n|:--|:--|:--|\n| Bob | happy | Cooking and baking | \n| Sally | wistful | Running marathons **barefoot** | \n| Mary | energetic | Playing multiple games of chess simultaneously | \n\n#### Code Block (fourth level header)\n\n```\n// This code is only here to illustrate a code block.\nWord.run(function (context) {\n var body = context.document.body;\n body.clear();\n return context.sync().then(function () {\n console.log('Cleared the body contents.');\n });\n})\n```\n\n### Paragraph with Web Link (third level header)\n\nFor more information about Office host application and server requirements, see [Requirements for running Office Add-ins](https://msdn.microsoft.com/EN-US/library/office/dn833104.aspx). \n\n##### Complex List (fifth level header)\n\nThere can be up to nine levels in a list.\n\n* Top level is bullet\n * Second level is bullet\n * Another second level item\n 1. Third level is numeric\n 1. Fourth level is numeric\n 1. Another fourth level item.\n * Fifth level is bullet\n 1. Sixth level is numeric\n 1. Another sixth level item\n * Back to the fifth level\n * Back to the sixth level\n * Seventh is bullet\n 1. Eighth is numeric\n * Ninth is bullet\n * Another ninth level item\n 1. Another eighth level item\n * Another seventh level\n * Another sixth level item\n 1. Another fourth level item\n 1. Another third level item\n * Another second level item\n* Another top-level item\n"; 16 | 17 | window.WordMarkdownConversion = WordMarkdownConversion; 18 | })(); -------------------------------------------------------------------------------- /Word-Add-in-JavaScript-MDConversionWeb/Home.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | /// <reference path="/Scripts/FabricUI/message.banner.js" /> 7 | /// <reference path="https://appsforoffice.microsoft.com/lib/beta/hosted/office.js" /> 8 | 9 | 10 | (function () { 11 | "use strict"; 12 | 13 | var WordMarkdownConversion = window.WordMarkdownConversion || {}; 14 | 15 | // The initialize function must be defined each time a new page is loaded. 16 | Office.initialize = function (reason) { 17 | $(document).ready(function () { 18 | // Initialize the FabricUI notification mechanism and hide it 19 | var element = document.querySelector('.ms-MessageBanner'); 20 | FabricComponents.messageBanner = new FabricComponents.MessageBanner(element); 21 | FabricComponents.messageBanner.hideBanner(); 22 | 23 | if (!Office.context.requirements.isSetSupported('WordApi', '1.2')) { 24 | $('#subtitle').text("Oops!"); 25 | $("#template-description").text("Sorry, this sample requires Word 2016 or later. The buttons will not convert your document."); 26 | return; 27 | } 28 | 29 | $('#convert-to-markdown').click(WordMarkdownConversion.convertToMarkdown); 30 | $('#convert-to-word').click(WordMarkdownConversion.convertToWord); 31 | $('#insert-test-Word-doc').click(WordMarkdownConversion.insertWordDoc); 32 | $('#insert-test-MD-doc').click(WordMarkdownConversion.insertMDDoc); 33 | }); 34 | }; 35 | 36 | WordMarkdownConversion.convertToWord = function () { 37 | 38 | Word.run(function (context) { 39 | var paragraphs = context.document.body.paragraphs.load('text'); 40 | 41 | // The following object enables the code to initialize data objects, 42 | // that are shared across multiple "then" callbacks within the Word.run, 43 | // closer to where they are used. 44 | var sharedDataObjects = { 45 | 46 | /// <field name="paragraphs" type="Word.ParagraphCollection" /> 47 | paragraphs: paragraphs, 48 | 49 | // There are Markdown lists, but no Word lists, at the start, 50 | // so we can't load them until we've created some. See the 51 | // convertMDListsToWord method below. 52 | /// <field name="lists" type="Word.ListCollection" /> 53 | lists: null, 54 | 55 | // Holds groups of paragraphs belonging to MD lists. 56 | /// <field type="Array" elementType="Word.ParagraphCollection" /> 57 | mdListItems: [], 58 | 59 | // Inline ranges can't be loaded until all paragraph processing is 60 | // done because the paragraphs that contain these ranges may be recreated. 61 | // E.g., MD tables are _replaced_ with Word tables, not converted. 62 | /// <field type="Array" elementType="Word.Range" /> 63 | mdHyperlinkRanges: [], 64 | /// <field type="Array" elementType="Word.Range" /> 65 | mdBoldRanges: [], 66 | /// <field type="Array" elementType="Word.Range" /> 67 | candidateMDItalicRanges: [] 68 | }; 69 | 70 | return context.sync() 71 | .then(function () { 72 | queueRemovalOfExtraBlankLines(sharedDataObjects.paragraphs); 73 | queueConversionOfMDHeadersToWord(sharedDataObjects.paragraphs); 74 | queueConversionOfMDCodeBlocksToWord(sharedDataObjects.paragraphs); 75 | queueCreationOfWordTables(sharedDataObjects.paragraphs); 76 | 77 | // Now that the table data is moved into a Word tables, delete the 78 | // paragraphs that comprise the original MD tables. But to cope with 79 | // a quirk in paragraph deletion the paragraphs collection must be 80 | // reloaded before we can accurately delete any paragraphs. 81 | sharedDataObjects.paragraphs = context.document.body.paragraphs.load('text'); 82 | }) 83 | .then(context.sync) 84 | .then(function () { 85 | queueDeletionOfMDTables(sharedDataObjects.paragraphs); 86 | queueCreationOfWordLists(sharedDataObjects.paragraphs, sharedDataObjects.mdListItems); 87 | 88 | // Load the Word lists (which now have just one item each) so we can add items to 89 | // them. 90 | sharedDataObjects.lists = context.document.body.lists.load('id, paragraphs/text'); 91 | }) 92 | .then(context.sync) 93 | .then(function () { 94 | queueAdditionOfItemsToWordLists(sharedDataObjects.lists, sharedDataObjects.mdListItems); 95 | 96 | // Cannot load bold or italic text or hyperlink ranges earlier because some 97 | // paragraphs in tables (and the inline ranges within them) get recreated when 98 | // the Word tables are created. 99 | // Find and load all bold and hypertext ranges. (Italic ranges have to wait. See below 100 | // for why.) 101 | sharedDataObjects.mdHyperlinkRanges = queueFetchOfInlineRanges('hyperlink', context).load('text'); 102 | sharedDataObjects.mdBoldRanges = queueFetchOfInlineRanges('bold', context).load('text'); 103 | }) 104 | .then(context.sync) 105 | .then(function () { 106 | queueConversionOfMDHyperlinksToWord(sharedDataObjects.mdHyperlinkRanges); 107 | queueConversionOfMDBoldStringsToBoldWordRanges(sharedDataObjects.mdBoldRanges); 108 | /* 109 | Because ranges enclosed in "**" (the MD bold symbol) are a subset of 110 | ranges enclosed by "*" (the MD italic symbol), the bold ranges have to 111 | be processed -- including removing the enclosing "**" -- and synchronized 112 | before the italic ranges can be processed, or even loaded. 113 | */ 114 | }) 115 | .then(context.sync) 116 | .then(function () { 117 | sharedDataObjects.candidateMDItalicRanges = queueFetchOfInlineRanges('italic', context).load('text'); 118 | }) 119 | .then(context.sync) 120 | .then(function () { 121 | queueConversionOfMDItalicStringsToItalicWordRanges(sharedDataObjects.candidateMDItalicRanges); 122 | }) 123 | .then(context.sync); 124 | // The last "context.sync" is optional, assuming there is at least one earlier 125 | // "context.sync", since Word.run will do an automatic sync at the end of 126 | // the batch if there are any pending actions. But it's a best-practice to 127 | // do an explicit sync. 128 | }) 129 | .catch(WordMarkdownConversion.errorHandler); 130 | 131 | function queueConversionOfMDHeadersToWord(paragraphs) { 132 | /// <param name="paragraphs" type="Word.ParagraphCollection" /> 133 | 134 | paragraphs.items.forEach(function (paragraph) { 135 | 136 | // In Markdown, all, and only, headers begin with '# ' or '## ' or '### ', etc. 137 | if (paragraph.text.indexOf('# ') >= 0) { 138 | var parsedParagraph = paragraph.text.split('# '); 139 | paragraph.insertText(parsedParagraph[1], "Replace"); 140 | 141 | // Note: parsedParagraph[0] does not include the split string '# ', so it 142 | // has one fewer '#' character than its heading level. 143 | switch (parsedParagraph[0]) { 144 | case '': 145 | // Use the locale-neutral styleBuiltIn property, so this works 146 | // in non-English Word. 147 | paragraph.styleBuiltIn = "Heading1"; 148 | break; 149 | case '#': 150 | paragraph.styleBuiltIn = "Heading2"; 151 | break; 152 | case '##': 153 | paragraph.styleBuiltIn = "Heading3"; 154 | break; 155 | case '###': 156 | paragraph.styleBuiltIn = "Heading4"; 157 | break; 158 | case '####': 159 | paragraph.styleBuiltIn = "Heading5"; 160 | break; 161 | case '#####': 162 | paragraph.styleBuiltIn = "Heading6"; 163 | break; 164 | default: 165 | // Handle corrupted MD headings. (Markdown only supports 6 heading levels.) 166 | throw new Error("Invalid Markdown header: \"" + paragraphs.text + "\". Must begin with 1 to 6 '#' characters followed by a space."); 167 | break; 168 | } 169 | } 170 | }) 171 | } 172 | 173 | function queueCreationOfWordTables(paragraphs) { 174 | /// <param name="paragraphs" type="Word.ParagraphCollection" /> 175 | 176 | var previousParagraphIsInTable = false; 177 | var newWordTable; 178 | var firstRow; 179 | 180 | paragraphs.items.forEach(function (paragraph) { 181 | 182 | // Assumption: Any paragraph that begins and ends with a "|" symbol 183 | // is a Markdown table row. 184 | var mdTableRowParagraph = /\|.*\|/; 185 | if (mdTableRowParagraph.test(paragraph.text)) { 186 | 187 | // Every "|" except the last one is the start of a cell/column. 188 | var cells = paragraph.text.split('|'); 189 | 190 | // The cells var contains empty items for the starting and ending "|", 191 | // but these won't be cells in the Word table, so remove them. 192 | var properCells = []; 193 | 194 | // Loop from the 2nd through the next-to-last. 195 | for (var j = 1; j < cells.length - 1; j++) { 196 | properCells.push(cells[j]); 197 | } 198 | 199 | if (!previousParagraphIsInTable) { 200 | 201 | // This is a table row, but the previous paragraph was not, 202 | // so we are at the start of a table. 203 | previousParagraphIsInTable = true; 204 | 205 | // Create a Word Table object. 206 | newWordTable = paragraph.insertTable(1, properCells.length, "Before"); 207 | firstRow = newWordTable.rows.getFirst(); 208 | 209 | // Make it resemble standard tables on GitHub. 210 | newWordTable.headerRowCount = 1; 211 | 212 | // In the Table Tools | Design tab of the Word ribbon, each built-in table 213 | // style has a name which you can see by hovering the cursor over the 214 | // style. Those names (with the spaces removed) are the possible values 215 | // of Table.styleBuildIn. 216 | newWordTable.styleBuiltIn = "PlainTable1"; 217 | 218 | // Two modifications of PlainTable1 make a better match for GitHub tables. 219 | newWordTable.styleBandedRows = false; 220 | newWordTable.styleFirstColumn = false; 221 | } 222 | 223 | // Copy the cells from the MD pargraph to the new row, 224 | // but skip the Markdown header separator row. 225 | var shouldNotSkip = !(paragraph.text.indexOf(':-') >= 0) 226 | && 227 | !(paragraph.text.indexOf(':=') >= 0); 228 | if (shouldNotSkip) { 229 | var newRow; 230 | if (firstRow) { 231 | newRow = firstRow; 232 | firstRow = void 0; // Make firstRow undefined again. 233 | } else { 234 | var rowCollection = newWordTable.addRows("End", 1); 235 | newRow = rowCollection.getFirst(); 236 | } 237 | 238 | // Writing to row values requires a 2D array. 239 | var outerArray = []; 240 | outerArray.push(properCells); 241 | newRow.values = outerArray; 242 | } 243 | } 244 | else if (previousParagraphIsInTable) { 245 | 246 | // This parapraph is not in the table, but the previous one was, 247 | // so the table ended. 248 | previousParagraphIsInTable = false; 249 | newWordTable = null; 250 | firstRow = null; 251 | } 252 | }) 253 | } 254 | 255 | function queueDeletionOfMDTables(paragraphs) { 256 | /// <param name="paragraphs" type="Word.ParagraphCollection" /> 257 | 258 | // Delete the paragraphs that comprise the original MD tables. 259 | paragraphs.items.forEach(function (paragraph) { 260 | var mdTableRowParagraph = /\|.*\|/; 261 | if (mdTableRowParagraph.test(paragraph.text)) { 262 | paragraph.delete(); 263 | } 264 | }) 265 | } 266 | 267 | function queueConversionOfMDCodeBlocksToWord(paragraphs) { 268 | /// <param name="paragraphs" type="Word.ParagraphCollection" /> 269 | 270 | var inCodeBlock = false; 271 | 272 | paragraphs.items.forEach(function (paragraph) { 273 | if (paragraph.text === '```') { 274 | if (!inCodeBlock) { 275 | // This is the start of a MD code block. 276 | inCodeBlock = true; 277 | // Delete the opening '```' paragraph. 278 | paragraph.delete(); 279 | } else { 280 | // This is the end of an MD code block. 281 | inCodeBlock = false; 282 | // Delete the closing '```' paragraph. 283 | paragraph.delete(); 284 | } 285 | } 286 | else if (inCodeBlock) { 287 | // Make it somewhat resemble GitHub code blocks. 288 | paragraph.styleBuiltIn = 'NoSpacing'; 289 | paragraph.font.name = 'Consolas'; 290 | paragraph.font.highlightColor = "LightGray"; 291 | } 292 | }) 293 | } 294 | 295 | function queueCreationOfWordLists(paragraphs, mdListItems) { 296 | /// <param name="paragraphs" type="Word.ParagraphCollection" /> 297 | /// <param name="mdListItems" type="Array" elementType="Word.ListCollection" /> 298 | 299 | var inList = false; 300 | var blockOfMDListItems = []; 301 | 302 | var mdListItemParagraph = /^\s*(\*|[0-9]\.)\s.*$/; 303 | var mdNumberListItemMarker = /[0-9].\s/; 304 | 305 | paragraphs.items.forEach(function (paragraph) { 306 | if (mdListItemParagraph.test(paragraph.text)) { 307 | if (!inList) { 308 | 309 | // This is the start of a list. 310 | inList = true; 311 | var list = paragraph.startNewList(); 312 | 313 | // A new list defaults to bullet, so it must be changed if it is 314 | // a numbered list. Assumption: A string "n. " (for some n) will appear 315 | // in a list item only if it is at the start of a numeric list item. 316 | if (paragraph.text.search(mdNumberListItemMarker) >= 0) { 317 | 318 | // A Markdown list that begins at a level other than 0 does not render 319 | // properly, so we make the assumption that all lists in the Markdown 320 | // begin at level 0. 321 | list.setLevelNumbering(0, 'Arabic', [0, "."]); 322 | list.setLevelStartingNumber(0, 1); 323 | /* 324 | No need to remove the original "n. " string (for some n) 325 | from the start of the paragraph. Word is intelligent enough 326 | to remove that automatically. 327 | */ 328 | } 329 | /* 330 | No need for an 'else' clause to format a bullet list, because Word 331 | automatically formats a bullet list item and even removes the "* " 332 | string from the start. 333 | */ 334 | } else { 335 | // The paragraph belongs to a list that has already started. 336 | // Add it to an array so that it can be added to the list object 337 | // with Paragraph.attachToList after the next sync. 338 | blockOfMDListItems.push(paragraph); 339 | } 340 | } else { 341 | if (inList) { 342 | // This paragraph is not in a list, but the preceding one 343 | // was, so the list has ended. 344 | // Assumption: all lists have at least 2 items. 345 | inList = false; 346 | mdListItems.push(blockOfMDListItems); 347 | blockOfMDListItems = []; 348 | } 349 | } 350 | }) 351 | } 352 | 353 | function queueAdditionOfItemsToWordLists(lists, mdListItems) { 354 | /// <param name="lists" type="Word.ListCollection" /> 355 | /// <param name="mdListItems" type="Array" elementType="Word.ListCollection" /> 356 | 357 | var mdListLevelTypeMarker = /(\*\s|[0-9].\s)/; 358 | var mdNumberListItemMarker = /[0-9].\s/; 359 | 360 | // Add addtional items to lists. Each item in mdListItems is an array of paragraphs 361 | // that represent the 2nd through last items in a list. 362 | // Each item in the mdListItems array was created immediately after the corresponding 363 | // Word list was created, so they have matching array indexes; mdListItems[i] has the 364 | // 2nd through last items that belong to the list lists.items[i]. 365 | for (var i = 0; i < lists.items.length; i++) { 366 | for (var j = 0; j < mdListItems[i].length; j++) { 367 | 368 | var parsedItem = mdListItems[i][j].text.split(mdListLevelTypeMarker); 369 | 370 | // To the left of the "* " or "n. " (for some n), there are four space 371 | // characters for every level deep of the list item. 372 | var mdLevel = (parsedItem[0].length / 4); 373 | 374 | mdListItems[i][j].attachToList(lists.items[i].id, mdLevel); 375 | mdListItems[i][j].insertText(parsedItem[2], 'Replace') 376 | 377 | // If the list item is numbered, set its numeric style. 378 | if (mdNumberListItemMarker.test(parsedItem[1])) { 379 | setNumericStyle(lists.items[i], mdLevel); 380 | } 381 | } 382 | } 383 | } 384 | 385 | function setNumericStyle(wordListObject, listLevel) { 386 | 387 | // Rotate among some available numeric styles. The style repeats every 388 | // 4th level. 389 | var level = listLevel % 4; 390 | 391 | var numericStyle; 392 | switch (level) { 393 | case 0: // listLevel was 0, 4, or 8. 394 | numericStyle = 'Arabic'; 395 | break; 396 | case 1: 397 | numericStyle = 'UpperLetter'; 398 | break; 399 | case 2: 400 | numericStyle = 'LowerLetter'; 401 | break; 402 | case 3: 403 | numericStyle = 'LowerRoman'; 404 | break; 405 | default: 406 | throw new Error(level + " is not a valid list level. The maximum is 9."); 407 | break; 408 | } 409 | wordListObject.setLevelNumbering(level, numericStyle, [level, "."]); 410 | wordListObject.setLevelStartingNumber(level, 1); 411 | } 412 | 413 | function queueFetchOfInlineRanges(type, context) { 414 | var searchWildcardExpression; 415 | 416 | // A Word wildcard expressions is like a RegEx, but to escape a character 417 | // wrap it in "[]" instead of preceding it with "\". 418 | switch (type) { 419 | case 'hyperlink': 420 | // Markdown hyperlinks have the pattern [link lable](URL). 421 | searchWildcardExpression = '[[]*[]][(]*[)]'; 422 | break; 423 | case 'bold': 424 | // Markdown bold strings have the pattern **bold text here**. 425 | searchWildcardExpression = '[*][*]*[*][*]'; 426 | break; 427 | case 'italic': 428 | // Markdown italic strings have the pattern *italic text here*. 429 | searchWildcardExpression = '[*]<*>[*]'; 430 | break; 431 | default: 432 | throw new Error("Unexpected range type: " + type); 433 | break; 434 | } 435 | return context.document.body.search(searchWildcardExpression, { 436 | matchWildCards: true 437 | }); 438 | /* 439 | Word search treats a literal "." character as a literal "*" character, so when 440 | searching for Italic -- [*]<*>[*] --, the preceding search results include ranges 441 | flanked by "." and ranges flanked by "*", but only the latter are Markdown italic 442 | ranges. After the next context.sync, the bogus hits must be removed. 443 | */ 444 | } 445 | 446 | function queueConversionOfMDHyperlinksToWord(mdHyperlinkRanges) { 447 | /// <param name="mdHyperlinkRanges" type="Array" elementType="Word.Range" /> 448 | 449 | mdHyperlinkRanges.items.forEach(function (hyperlinkRange) { 450 | // The text of each item has the pattern [link lable](URL). 451 | var parsedHyperlink = hyperlinkRange.text.split(']('); 452 | 453 | // The label part becomes the entire string. 454 | var trimmedLabel = parsedHyperlink[0].split('[')[1]; 455 | 456 | // Next line empties the text AND the URL of the hyperlink. 457 | hyperlinkRange.clear(); 458 | hyperlinkRange.insertText(trimmedLabel, "Start"); 459 | 460 | // Process the URL part. This must be done after the label part because the clear() 461 | // command above blanks the Range.hyperlink property. 462 | var trimmedURL = parsedHyperlink[1].split(')')[0]; 463 | hyperlinkRange.hyperlink = trimmedURL; 464 | }) 465 | } 466 | 467 | function queueConversionOfMDBoldStringsToBoldWordRanges(mdBoldRanges) { 468 | /// <param name="mdBoldRanges" type="Array" elementType="Word.Range" /> 469 | 470 | // Remove the MD bold markers ('**') and set the Word bold font. 471 | mdBoldRanges.items.forEach(function (boldRange) { 472 | var parsedBoldRange = boldRange.text.split('**'); 473 | var trimmedBoldRange = parsedBoldRange[1]; 474 | boldRange.insertText(trimmedBoldRange, 'Replace'); 475 | boldRange.font.bold = true; 476 | }) 477 | } 478 | 479 | function queueConversionOfMDItalicStringsToItalicWordRanges(candidateMDItalicRanges) { 480 | /// <param name="candidateMDItalicRanges" type="Array" elementType="Word.Range" /> 481 | 482 | // Create a new array of Range objects that includes only those whose text begins with '*'. 483 | // See the queueFetchOfInlineRanges method for why this is required. 484 | var genuineMDItalicRanges = candidateMDItalicRanges.items.filter(function (item) { 485 | return item.text.indexOf('*') === 0; 486 | }) 487 | 488 | // Remove the MD italic markers ('*') and set the Word italic font. 489 | genuineMDItalicRanges.forEach(function (italicRange) { 490 | var parsedItalicRange = italicRange.text.split('*'); 491 | var trimmedItalicRange = parsedItalicRange[1]; 492 | italicRange.insertText(trimmedItalicRange, 'Replace'); 493 | italicRange.font.italic = true; 494 | }) 495 | } 496 | 497 | function queueRemovalOfExtraBlankLines(paragraphs) { 498 | /// <param name="paragraphs" type="Word.ParagraphCollection" /> 499 | 500 | // Markdown renders two or more blank lines as a single line, but 501 | // Word renders them all. To get a better approximation in Word of 502 | // the appearence of the document in rendered Markdown, remove excess 503 | // blank lines. 504 | var previousParagraphIsBlankLine = false; 505 | 506 | paragraphs.items.forEach(function (paragraph) { 507 | if (paragraph.text === '') { 508 | if (!previousParagraphIsBlankLine) { 509 | // This the first of possibly multiple blank lines. 510 | previousParagraphIsBlankLine = true; 511 | } else { 512 | // This is the second (or later) consecutive blank line, 513 | // so queue a command to delete it. 514 | paragraph.delete(); 515 | } 516 | } else { 517 | previousParagraphIsBlankLine = false; 518 | } 519 | }) 520 | } 521 | } 522 | 523 | WordMarkdownConversion.insertWordDoc = function () { 524 | Word.run(function (context) { 525 | // WordMarkdownConversion.sampleWordDocument is defined in SampleContent.js 526 | context.document.body.insertFileFromBase64(WordMarkdownConversion.sampleWordDocument, "Replace"); 527 | return context.sync(); 528 | }) 529 | .catch(WordMarkdownConversion.errorHandler); 530 | } 531 | 532 | WordMarkdownConversion.insertMDDoc = function () { 533 | Word.run(function (context) { 534 | // WordMarkdownConversion.sampleMDDocument is defined in SampleContent.js 535 | context.document.body.insertText(WordMarkdownConversion.sampleMDDocument, "Replace"); 536 | return context.sync(); 537 | }) 538 | .catch(WordMarkdownConversion.errorHandler); 539 | } 540 | 541 | WordMarkdownConversion.convertToMarkdown = function () { 542 | Word.run(function (context) { 543 | 544 | // Load as many objects as possible with as few as possible calls of context.sync. 545 | // But load only the properties that are actually read by the code. 546 | var paragraphs = context.document.body.paragraphs.load('tableNestingLevel, font, styleBuiltIn'); 547 | var hyperlinks = context.document.body.getRange().getHyperlinkRanges().load('hyperlink, text'); 548 | var lists = context.document.body.lists.load('levelTypes'); 549 | var tables; // Cannot load tables yet. See below for why. 550 | 551 | // The following object enables the code to initialize data objects, 552 | // that are shared across multiple "then" callbacks within the Word.run, 553 | // closer to where they are used. 554 | var sharedDataObjects = { 555 | 556 | /// <field name="paragraphs" type="Word.ParagraphCollection" /> 557 | paragraphs: paragraphs, 558 | 559 | /// <field name="hyperlinks" type="Word.RangeCollection" /> 560 | hyperlinks: hyperlinks, 561 | 562 | /// <field name="lists" type="Word.ListCollection" /> 563 | lists: lists, 564 | 565 | /// <field name="tables" type="Word.TableCollection" /> 566 | tables: tables, 567 | 568 | // Holds an array of Range collections, one collection per paragraph. Each collection 569 | // is the words of the paragraph. 570 | /// <field name="wordRangesInParagraphs" type="Array" elementType="Word.RangeCollection" /> 571 | wordRangesInParagraphs: [], 572 | 573 | // Holds an array of objects (one for each level of each list in the document) 574 | // that record the level, [sub]list type (Bullet or Number), and child paragraphs 575 | // at that level of that list. 576 | levelParagraphs: [] 577 | }; 578 | return context.sync() 579 | .then(function () { 580 | /* 581 | Now that paragraphs are loaded, load the word ranges within them 582 | that the queueConversionOfBoldAndItalicRanges method is going to process. 583 | */ 584 | sharedDataObjects.paragraphs.items.forEach(function (paragraph) { 585 | 586 | // Skip headings 587 | if (paragraph.styleBuiltIn.indexOf('Heading') === -1) { 588 | 589 | // Note: wordRanges include "words" with immediately following punctuation 590 | // marks. Example: "something," is a word range. 591 | var wordRanges = paragraph.getTextRanges([' '], true); 592 | 593 | // Queue a command to load all the word ranges in the paragraph. 594 | wordRanges.load("font/bold, font/italic"); 595 | sharedDataObjects.wordRangesInParagraphs.push(wordRanges); 596 | } 597 | }) 598 | /* 599 | Now that the lists are loaded, load the paragraphs at various 600 | list levels that the queueConversionOfLists method is going to process. 601 | */ 602 | sharedDataObjects.lists.items.forEach(function (list) { 603 | 604 | // For all levels of the list. (Word has a 9 level maximum.) 605 | for (var j = 0; j < 9; j++) { 606 | 607 | // Create an object that will record the level and list type 608 | // (i.e., Bullet or Number) of the items of the level/list. 609 | var paragraphsAtCurrentLevel = { 610 | level: j, 611 | listTypeAtLevel: list.levelTypes[j] 612 | } 613 | 614 | // Queue commands to add the items (paragraphs) themselves to the object and load them. 615 | paragraphsAtCurrentLevel.paragraphCollection = list.getLevelParagraphs(j).load(); 616 | sharedDataObjects.levelParagraphs.push(paragraphsAtCurrentLevel); 617 | } 618 | }) 619 | }) 620 | .then(context.sync) 621 | .then(function () { 622 | // Need the file path to handle a quirk in how Word stores bookmark 623 | // hyperlinks. See the ensureProperMDLink function. 624 | WordMarkdownConversion.fileUrl = getDocumentFilePath(); 625 | }) 626 | 627 | // Run the various conversion helper methods. None of these have any 628 | // internal calls of load() or context.sync() or async calls. 629 | .then(function () { 630 | queueConversionOfBoldAndItalicRanges(sharedDataObjects.wordRangesInParagraphs); 631 | queueConversionOfHyperlinkRanges(sharedDataObjects.hyperlinks); 632 | queueConversionOfCodeBlocks(sharedDataObjects.paragraphs); 633 | queueAdditionOfBlankLineAfterNormalParagraphs(sharedDataObjects.paragraphs); 634 | queueConversionOfHeadings(sharedDataObjects.paragraphs); 635 | queueConversionOfLists(sharedDataObjects.levelParagraphs); 636 | }) 637 | .then(function () { 638 | // The tables cannot be loaded until now because the queueConversionOfBoldAndItalicRanges() 639 | // and queueConversionOfHyperlinkRanges() methods may have changed cell contents in ways 640 | // that must be synchronized before the tables are converted. 641 | sharedDataObjects.tables = context.document.body.tables.load('values, rowCount'); 642 | }) 643 | .then(context.sync) 644 | .then(function () { 645 | queueConversionOfTables(sharedDataObjects.tables); 646 | }) 647 | .then(context.sync); 648 | // The last "context.sync" is optional, assuming there is at least one earlier 649 | // "context.sync", since Word.run will do an automatic sync at the end of 650 | // the batch if there are any pending actions. But it's a best-practice to 651 | // do an explicit sync. 652 | }).catch(WordMarkdownConversion.errorHandler); 653 | 654 | 655 | // Checks each word to see if it's formatted italic or bold, and if so, 656 | // adds the appropriate Markdown symbols ("*" for italic, "**" for bold). 657 | function queueConversionOfBoldAndItalicRanges(wordRangesInParagraphs) { 658 | /// <param name="wordRangesInParagraphs" type="Array" elementType="Word.ParagraphCollection" /> 659 | 660 | wordRangesInParagraphs.forEach(function (wordRangesInSingleParagraph) { 661 | wordRangesInSingleParagraph.items.forEach(function (word, index) { 662 | 663 | // If several words in a row are styled the same, 664 | // the Markdown code is only output at the beginning and end of the string. 665 | var previousWord = wordRangesInSingleParagraph.items[index - 1]; 666 | var nextWord = wordRangesInSingleParagraph.items[index + 1]; 667 | 668 | // Note: word.font.bold is true only when the WHOLE range, including trailing 669 | // punctuation, if any, is bold. 670 | if (word.font.bold) { 671 | if ((typeof previousWord === 'undefined') || !previousWord.font.bold) { 672 | word.insertText('**', 'Start'); 673 | } 674 | if ((typeof nextWord === 'undefined') || !nextWord.font.bold) { 675 | word.insertText('**', 'End'); 676 | } 677 | } 678 | // Note: word.font.italic is true only when the WHOLE range, including trailing 679 | // punctuation, is any, is italic. 680 | if (word.font.italic) { 681 | if ((typeof previousWord === 'undefined') || !previousWord.font.italic) { 682 | word.insertText('*', 'Start'); 683 | } 684 | if ((typeof nextWord === 'undefined') || !nextWord.font.italic) { 685 | word.insertText('*', 'End'); 686 | } 687 | } 688 | }) 689 | }) 690 | } 691 | 692 | // Gets a collection of all of the hyperlinks in a document and 693 | // converts them to Markdown style hyperlinks. 694 | function queueConversionOfHyperlinkRanges(hyperlinks) { 695 | /// <param name="hyperlinks" type="Array" elementType="Word.RangeCollection" /> 696 | 697 | hyperlinks.items.forEach(function (link) { 698 | var properLinkURL = ensureProperMDLink(link); 699 | var mdLink = '[' + link.text + '](' + properLinkURL + ') '; 700 | 701 | // To remove a Word hyperlink, blank the URL. 702 | link.hyperlink = ""; 703 | link.insertText(mdLink, 'Replace'); 704 | }) 705 | 706 | function ensureProperMDLink(hyperlinkRange) { 707 | var linkURL = hyperlinkRange.hyperlink; 708 | 709 | // If the link.hyperlink property consists of only a bookmark; that is, 710 | // begins with a "#", Office appends the full local file name of the current 711 | // document to the front of it. (This will be blank, if the file has never 712 | // been saved.) 713 | // The next few lines reverse that because bookmark URLs in Markdown 714 | // must contain only the bookmark, so that the Markdown renderer is able to 715 | // append the URL of the online MD file to the front of the bookmark. 716 | var parsedMDLink = linkURL.split('#'); 717 | if (parsedMDLink[0] === WordMarkdownConversion.fileUrl) { 718 | linkURL = '#' + parsedMDLink[1]; 719 | } 720 | return linkURL; 721 | } 722 | } 723 | 724 | // Convert blocks of code paragraphs to Markdown code blocks. 725 | function queueConversionOfCodeBlocks(paragraphs) { 726 | /// <param name="paragraphs" type="Word.ParagraphCollection" /> 727 | 728 | var previousParagraphIsCode = false; 729 | var codeBlockParagraphs = []; 730 | 731 | paragraphs.items.forEach(function (paragraph) { 732 | 733 | // Only process a paragraph outside of a table. 734 | if (paragraph.tableNestingLevel === 0) { 735 | 736 | // Assumption: Code block paragraphs will use Consolas font. 737 | if (paragraph.font.name === 'Consolas') { 738 | if (!previousParagraphIsCode) { 739 | 740 | // This paragraph is Code, but the previous one was not, 741 | // so we are at the start of a code block. Add the ``` above the 742 | // paragraph to start the Markdown code block. 743 | var tripleTickParagraph = paragraph.insertParagraph('```', 'Before'); 744 | previousParagraphIsCode = true; 745 | codeBlockParagraphs.push(tripleTickParagraph); 746 | } 747 | // Store in order to change its font and background later. 748 | codeBlockParagraphs.push(paragraph); 749 | } 750 | 751 | if ((paragraph.font.name != 'Consolas') && (previousParagraphIsCode)) { 752 | 753 | // This parapraph is not Code, but the previous one was, 754 | // so add the Markdown ``` to end the code block. 755 | 756 | // But Word gives a paragraph that is inserted "Before" the same style. 757 | // So change to Normal style temporarily to avoid, for example, giving 758 | // the ``` a Header 2 style which would result in Markdown: "## ```". 759 | var oldStyle = paragraph.styleBuiltIn; 760 | paragraph.styleBuiltIn = 'Normal'; 761 | paragraph.insertParagraph('```', 'Before'); 762 | paragraph.styleBuiltIn = oldStyle; 763 | previousParagraphIsCode = false; 764 | } 765 | } 766 | }) 767 | 768 | // Change font and background color of code block paragraphs to make 769 | // look more like plain Markdown text. 770 | codeBlockParagraphs.forEach(function (codeParagraph) { 771 | codeParagraph.font.name = 'Calibri (Body)'; 772 | codeParagraph.font.highlightColor = null; 773 | }) 774 | } 775 | 776 | // Formatting of Markdown text that follows an ordinary paragraph requires 777 | // a blank line after the paragraph, but Word paragraphs with Normal style 778 | // typically don't have one. Multiple blank lines are treated as one in Markdown, 779 | // So there's no harm if a blank line is added where there already is one. 780 | function queueAdditionOfBlankLineAfterNormalParagraphs(paragraphs) { 781 | /// <param name="paragraphs" type="Word.ParagraphCollection" /> 782 | 783 | paragraphs.items.forEach(function (paragraph) { 784 | 785 | // Only process a paragraph outside of a table. 786 | if (paragraph.tableNestingLevel === 0) { 787 | if (paragraph.styleBuiltIn === 'Normal') { 788 | paragraph.styleBuiltIn = 'Normal'; 789 | paragraph.insertParagraph('', 'After'); 790 | } 791 | } 792 | }) 793 | } 794 | 795 | // Finds all the headers in the document and converts them to Markdown. 796 | function queueConversionOfHeadings(paragraphs) { 797 | /// <param name="paragraphs" type="Word.ParagraphCollection" /> 798 | 799 | paragraphs.items.forEach(function (paragraph) { 800 | 801 | // Only headers have a styleBuiltIn value with "Heading" in the name. 802 | if (paragraph.styleBuiltIn.indexOf('Heading') === 0) { 803 | 804 | switch (paragraph.styleBuiltIn) { 805 | case 'Heading1': 806 | paragraph.insertText('# ', 'Start'); 807 | break; 808 | case 'Heading2': 809 | paragraph.insertText('## ', 'Start'); 810 | break; 811 | case 'Heading3': 812 | paragraph.insertText('### ', 'Start'); 813 | break; 814 | case 'Heading4': 815 | paragraph.insertText('#### ', 'Start'); 816 | break; 817 | case 'Heading5': 818 | paragraph.insertText('##### ', 'Start'); 819 | break; 820 | case 'Heading6': 821 | paragraph.insertText('###### ', 'Start'); 822 | break; 823 | default: 824 | // Markdown supports only 6 levels of headings. But instead of throwing an 825 | // error, just let a paragraph with a "Heading" style greater than 6 be 826 | // changed to a non-heading in Markdown by the first line after the switch block. 827 | break; 828 | } 829 | // Turn off Word heading formatting so it looks more like plain Markdown. 830 | paragraph.styleBuiltIn = 'Normal'; 831 | 832 | // Some Markdown renderers fail to correctly render lists or tables if the 833 | // immediately preceding, or following, paragraph is a header, but Word paragraphs 834 | // with a Header style typically are not followed/preceded by a blank line, 835 | // so add one. Multiple blank lines are treated as one in Markdown, so there's 836 | // no harm if a blank line is added where there already is one. 837 | paragraph.insertParagraph('', 'Before'); 838 | paragraph.insertParagraph('', 'After'); 839 | } 840 | }) 841 | } 842 | 843 | // Convert Word lists into Markdown syntax. 844 | function queueConversionOfLists(levelParagraphs) { 845 | /// <param name="levelParagraphs" type="Word.ParagraphCollection" /> 846 | 847 | // Note: levelParagraphs holds an array of objects (one for each level of each list in the document) 848 | // that record the level, [sub]list type [Bullet or Number], and child paragraphs 849 | // at that level of that list. 850 | levelParagraphs.forEach(function (levelDefinition) { 851 | 852 | // Note: levelDefinition.paragraphCollection is a Word.ParagraphCollection 853 | // levelDefinition.paragraphCollection.items is an array of Word.Paragraph objects. 854 | levelDefinition.paragraphCollection.items.forEach(function (wordParagraph) { 855 | 856 | var mdListItemPrefix = getMarkdownListItemPrefix(levelDefinition.listTypeAtLevel, 857 | levelDefinition.level); 858 | 859 | // Insert Markdown list item (level-relative and type-relative) prefix. 860 | wordParagraph.insertText(mdListItemPrefix, 'Start'); 861 | 862 | // Turn off Word list style, so the list resembles Markdown text. 863 | wordParagraph.styleBuiltIn = 'Normal'; 864 | }) 865 | }) 866 | 867 | // Returns a string of '* ' or '1. ' symbol, preceded by 4 spaces 868 | // for each level deep in a (possibly nested) list. 869 | function getMarkdownListItemPrefix(wordListType, listLevel) { 870 | 871 | var listTypeSymbol = getMarkdownSymbol(wordListType); 872 | var itemPrefix = ''; 873 | for (var i = 0; i < listLevel; i++) { 874 | itemPrefix = itemPrefix + " "; // 4 spaces 875 | } 876 | return itemPrefix + listTypeSymbol + ' '; 877 | 878 | function getMarkdownSymbol(wordListType) { 879 | switch (wordListType) { 880 | case 'Bullet': 881 | return '*'; 882 | case 'Number': 883 | return '1.'; 884 | case 'Picture': 885 | throw new Error("Cannot convert Word picture list type to Markdown."); 886 | break; 887 | default: 888 | throw new Error("Unknown Word list type. Should be 'Number', 'Bullet', or 'Picture'."); 889 | break; 890 | } 891 | } 892 | } 893 | } 894 | 895 | // Gets a collection of all of the tables in the document and converts 896 | // them to Markdown-style tables. 897 | function queueConversionOfTables(tables) { 898 | /// <param name="tables" type="Word.TableCollection" /> 899 | 900 | tables.items.forEach(function (table) { 901 | table.values.forEach(function (cellValues, index) { 902 | 903 | // Create a Markdown table above the Word table. Add each 904 | // row below the preceding row, which means just before the 905 | // Word table. 906 | var rowParagraph = table.insertParagraph('| ', 'Before'); 907 | rowParagraph.styleBuiltIn = 'Normal'; 908 | 909 | // Copy each cell from the Word table to the Markdown table. 910 | cellValues.forEach(function (cellValue) { 911 | rowParagraph.insertText(cellValue + ' | ', 'End'); 912 | }) 913 | 914 | // If the row that was just created is the first one, then insert the 915 | // Markdown separator row. (If your Markdown renderer supports rows 916 | // without headers -- GitHub and others do NOT -- then you could check 917 | // (table.heardRowCount > 0) to see if the Word table has a header.) 918 | if (index === 0) { 919 | var mdSeparatorRow = '|'; 920 | const mdSeparatorCell = ':--|'; 921 | 922 | // "for" instead of "forEach" because its only the length of cellValues 923 | // that matters. The loop does not read or write cellValues. 924 | for (var k = 0; k < cellValues.length; k++) { 925 | mdSeparatorRow = mdSeparatorRow + mdSeparatorCell; 926 | } 927 | table.insertParagraph(mdSeparatorRow, 'Before'); 928 | } 929 | }) 930 | // Remove the original Word table. 931 | table.delete(); 932 | }) 933 | } 934 | } 935 | 936 | // Gets the full path and file name of the Word document. 937 | function getDocumentFilePath() { 938 | 939 | // Wrap call to Office 2013 asynchronous method in a promise to be consistent with 940 | // the Office 2016 asynchronous architecture. 941 | return new OfficeExtension.Promise(function (resolve, reject) { 942 | try { 943 | // Need to use the Office 2013 JavaScript APIs to get the full file path and name. 944 | // This data is needed to handle a quirk in how Word stores bookmark hyperlinks. See 945 | // the method ensureProperMDLink in this file. Note: the Office.context.url 946 | // property returns an HTTP URL, not the file path and name that is needed in this case. 947 | Office.context.document.getFilePropertiesAsync(function (asyncResult) { 948 | resolve(asyncResult.value.url); 949 | }); 950 | } 951 | catch (error) { 952 | reject(WordMarkdownConversion.errorHandler(error)); 953 | } 954 | }) 955 | } 956 | 957 | WordMarkdownConversion.errorHandler = function (error) { 958 | WordMarkdownConversion.showNotification(error); 959 | console.log("Error: " + error); 960 | if (error instanceof OfficeExtension.Error) { 961 | console.log("Debug info: " + JSON.stringify(error.debugInfo)); 962 | console.log("Trace info: " + JSON.stringify(error.traceMessages)); 963 | } 964 | } 965 | 966 | // Helper function for displaying notifications in a message banner. 967 | WordMarkdownConversion.showNotification = function (content) { 968 | $("#notificationBody").text(content); 969 | FabricComponents.messageBanner.showBanner(); 970 | FabricComponents.messageBanner.toggleExpansion(); 971 | } 972 | 973 | window.WordMarkdownConversion = WordMarkdownConversion; 974 | })(); 975 | 976 | --------------------------------------------------------------------------------